home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 16 / CU Amiga Magazine's Super CD-ROM 16 (1997-10-16)(EMAP Images)(GB)[!][issue 1997-11].iso / CUCD / Online / HBBS / Source / Library / HBBSCommon.c < prev    next >
C/C++ Source or Header  |  1997-09-04  |  66KB  |  2,596 lines

  1. /*
  2.  
  3.   todo
  4.   ====
  5.  
  6.   remove CountListItems(), replace with HBBS_NodesInList()  :-)
  7.  
  8. */
  9.  
  10. #define HBBSCOMMON
  11. #define MAIN
  12.  
  13. #include <ctype.h>
  14. #include <time.h>
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18.  
  19. #include <exec/exec.h>
  20. #include <exec/types.h>
  21.  
  22. #include <dos/dos.h>
  23. #include <dos/dostags.h>
  24. #include <dos/filehandler.h>
  25. #include <dos/dosextens.h>
  26.  
  27. #include <libraries/reqtools.h>
  28.  
  29.  
  30. #include <clib/exec_protos.h>
  31. #include <clib/dos_protos.h>
  32. #include <clib/alib_protos.h>
  33. #include <clib/reqtools_protos.h>
  34.  
  35. #include <pragmas/exec_pragmas.h>
  36. #include <pragmas/dos_pragmas.h>
  37. #include <pragmas/reqtools_pragmas.h>
  38.  
  39.  
  40. #include "/common/types.h"
  41. #include "/common/errors.h"
  42. #include "/common/defines.h"
  43. #include "/common/structures.h"
  44. #include "/common/strings.h"
  45. #include "/common/files.h"
  46. #include "/common/release.h"
  47. // some forward defines
  48.  
  49. void __asm __saveds strNcpy(register __a0 UBYTE *dest,register __a1 UBYTE *source,register __d0 int chars);
  50. void __asm __saveds HBBS_rterror(register __a0 char *str);
  51. BOOL __asm __saveds AssignOK(register __a0 char *checkme );
  52. BOOL __asm __saveds HBBS_AddCfgItem(register __a0 struct CfgFileData *cfgfile,register __a1 UBYTE *itemname,register __a2 UBYTE *params);
  53. struct List __asm __saveds *HBBS_CreateList( void );
  54. void __asm __saveds HBBS_DateStrFromTM(register __a0 UBYTE *datestr, register __a1 struct tm *timestruct);
  55. V_BOOL __asm __saveds HBBS_AddCfgItemQuick(register __a0 struct CfgFileData *cfgfile,register __a1 char *ItemName, register __a2 char *Params);
  56. void   __asm __saveds HBBS_FlushConfig(register __a0 struct CfgFileData *cfgfile);
  57. BOOL __asm __saveds PathOK(register __a0 char *str);
  58.  
  59. // needed libs..
  60.  
  61. struct DosLibrary *DOSBase=NULL;
  62. struct ExecBase *SysBase=NULL;
  63. struct ReqToolsBase *ReqToolsBase=NULL;
  64.  
  65. char *versionstr="$VER: HBBSCommon.library "RELEASE_STR;
  66.  
  67. // global variables.. (keep to a minimum..)
  68.  
  69. #ifndef __SASC
  70.  
  71. struct LibBase {
  72.   struct Library base;
  73. };
  74.  
  75. #pragma libbase LibBase
  76. #endif
  77.  
  78. struct BBSGlobalData *BBSGlobal=NULL;
  79.  
  80. UBYTE *OPT_PRIV_LastUserNum="LastUserNum";
  81. UBYTE *OPT_PRIV_CallsEver="CallsEver";
  82.  
  83. char monthstr[12][4]={"JAN","FEB","MAR","APR","MAY","JUN","JUL","AUG","SEP","OCT","NOV","DEC"};
  84.  
  85.  
  86. // actual functions..
  87.  
  88. int __asm __saveds strNIcmp(register __a0 char *s1, register __a1 char *s2,register __d0 int n)
  89. {
  90.   char *cs1,*cs2;
  91.   int retval=-1;
  92.  
  93.   if (cs1=AllocVec(n+1,MEMF_PUBLIC))
  94.   {
  95.     if (cs2=AllocVec(n+1,MEMF_PUBLIC))
  96.     {
  97.       strNcpy(cs1,s1,n);
  98.       strNcpy(cs2,s2,n);
  99.       retval=stricmp(cs1,cs2);
  100.       FreeVec(cs2);
  101.     }
  102.     FreeVec(cs1);
  103.   }
  104.   return(retval);
  105. }
  106.  
  107. void __asm __saveds FreeStr(register __a0 char *str)
  108. {
  109.   if (str) FreeVec(str);
  110. }
  111.  
  112. char __asm __saveds *DupStr(register __a0 char *str)
  113. {
  114.   char *newstr=NULL;
  115.   if (str)
  116.   {
  117.     if (newstr=(char *)AllocVec(strlen(str)+1,MEMF_PUBLIC))
  118.     {
  119.       newstr[0]=0;
  120.       strcpy(newstr,str);
  121.     }
  122.   }
  123.   return(newstr);
  124. }
  125.  
  126. char __asm __saveds *FreeAndSet(register __a0 char **varname,register __a1 char *newstr)
  127. {
  128.   // this routines frees memory allocated to strings using strdup or
  129.   // and duplicates the string in newstr and sets varname to the newly allocated str
  130.  
  131.   if (*varname!=NULL)
  132.   {
  133.     FreeStr(*varname);
  134.     *varname=NULL;
  135.   }
  136.  
  137.   if (newstr)
  138.   {
  139.     *varname=DupStr(newstr);
  140.   }
  141.   return(*varname); // return varname if you want to test result..
  142. }
  143.  
  144.  
  145. V_BOOL __asm __saveds CheckBoolean(register __a0 char *str)
  146. {
  147.   if (stricmp(str,"TRUE")==0 || stricmp(str,"ON")==0 || stricmp(str,"YES")==0)
  148.     return(TRUE);
  149.   else
  150.     return(FALSE);
  151. }
  152.  
  153.  
  154. // creates a new node with ln_Name set to a copy of str, and appends it to the list specified
  155.  
  156. V_ERROR __asm __saveds NewStrNode(register __a0 char *str,register __a1 struct List *list)
  157. {
  158.   struct Node *NewNode;
  159.   V_ERROR retval=TYPE_MEMORY;
  160.  
  161.   if (NewNode=AllocVec(sizeof(struct Node),MEMF_PUBLIC|MEMF_CLEAR))
  162.   {
  163.     if ((str==NULL) || (NewNode->ln_Name=DupStr(str)))
  164.     {
  165.       AddTail(list,NewNode);
  166.       retval=ERR_NO_ERROR;
  167.     }
  168.     else
  169.     {
  170.       FreeVec(NewNode);
  171.     }
  172.   }
  173.   return(retval);
  174. }
  175.  
  176. void __asm __saveds UpperCase(register __a0 char *str)
  177. {
  178.   // converts str into uppercase
  179.  
  180.   short loop;
  181.  
  182.   for (loop=0;str[loop];loop++) str[loop]=toupper(str[loop]);
  183. }
  184.  
  185. char __asm __saveds *upcase(register __a0 char *str)
  186. {
  187.   // converts str into uppercase and returns a pointer to a new
  188.   // string.
  189.   // returns NULL if it fails.
  190.  
  191.   // dont forget to FreeStr() the output!
  192.  
  193.   char *outstr;
  194.  
  195.   if (outstr=DupStr(str))
  196.   {
  197.     UpperCase(outstr);
  198.   }
  199.   return(outstr);
  200. }
  201.  
  202. short __asm __saveds position(register __a0 char *substr,register __a1 char *str)
  203. {
  204.   // returns an character offset of a substring in a string
  205.   // this version is CASE SENSITIVE
  206.   // returns -1 if substring not found in the string
  207.  
  208.   char *whstr;
  209.   return((short)((whstr=strstr(str,substr)) ? (short)((LONG)whstr-(LONG)str) : -1));
  210. }
  211.  
  212. short __asm __saveds iposition(register __a0 char *substr,register __a1 char *str)
  213. {
  214.   // returns an character offset of a substring in a string
  215.   // this version is CASE INSENSITIVE
  216.   // returns -1 if substring not found in the string
  217.   //      or -2 if memory allocation error
  218.  
  219.   short where=-2;
  220.   char *isubstr,*istr;
  221.  
  222.   if (isubstr=upcase(substr))
  223.   {
  224.     if (istr=upcase(str))
  225.     {
  226.       where=position(isubstr,istr);
  227.       FreeStr(istr);
  228.     }
  229.     FreeStr(isubstr);
  230.   }
  231.   return(where);
  232. }
  233.  
  234. void __asm __saveds strfcpy(register __a0 char *dest,register __a1 char *source,register __d0 int from)
  235. {
  236.   /*
  237.      copy all chars from "source" to "dest" starting at offset "from"
  238.      (kinda the reverse from strncpy() )
  239.    */
  240.   int loop=from,pos=0;
  241.   if (from<=strlen(source)-1)
  242.   {
  243.     while (source[loop])
  244.     {
  245.       dest[pos]=source[loop];
  246.       loop++;
  247.       pos++;
  248.     }
  249.   }
  250.   dest[pos]=0;
  251. }
  252.  
  253. void __asm __saveds stripcr(register __a0 char *s)
  254. {
  255.   /* New Optimized Version 04-JAN-1996 */
  256.  
  257.   LONG Len;
  258.   if (s)
  259.   {
  260.     Len=strlen(s)-1; // set to point to last char in string 's'
  261.  
  262.     while (Len>=0 && (s[Len]=='\r' || s[Len]=='\n'))
  263.     {
  264.       s[Len--]=0; // string is now 1 char smaller, and overwrite the \r or \n with a null terminator
  265.     }
  266.   }
  267. }
  268.  
  269. UBYTE __asm __saveds  *StripComments(register __a0 char *s)
  270. {
  271.   /* New Optimized Version 04-JAN-1996 */
  272.  
  273.   // returns a pointer to the start of the comments too..
  274.  
  275.   UBYTE *strptr;
  276.  
  277.   if (strptr=strchr(s,';'))
  278.   {
  279.     *strptr=0;
  280.     strptr++; //we've just killed the ';' so point to next char..
  281.   }
  282.   return(strptr);
  283. }
  284.  
  285. void __asm __saveds StripSpaces(register __a0 char *s)
  286. {
  287.   /* New Optimized Version 04-JAN-1996 */
  288.   /* this version only parses the string once, much nicer.. */
  289.  
  290.   LONG len=strlen(s)-1;
  291.  
  292.   // while the last char is a ' ', set it to a 0
  293.   while (len>=0 && s[len]==' ') s[len--]=0;  // cooler Kompakt coding! :-)
  294. }
  295.  
  296. /* old version, too slow, keeps parsing strings..
  297. void __asm __saveds StripSpaces(register __a0 char *s)
  298. {
  299.   // while the last char is a ' ', set it to a 0
  300.   while (s[strlen(s)-1]==' ') s[strlen(s)-1]=0;  // Kompakt coding! :-)
  301. }
  302. */
  303. void __asm __saveds replace(register __a0 char *dest,register __a1 char *compare,register __a2 char *from,register __a3 char *to)
  304. {
  305.  
  306.   /*
  307.      replace all occurences of "from" in "compare" with "to" and store result in "dest"
  308.      (note: this is dead usefull!!!)
  309.  
  310.      e.g.  replace(dest,source,"Whops","Whoops!");
  311.  
  312.      compare and dest can be the same variable...
  313.  
  314.    */
  315.   int where;
  316.   char *mystring;
  317.  
  318.   if (mystring=DupStr(compare))
  319.   {
  320.     strcpy(dest,"");
  321.     do
  322.     {
  323.       where=position(from,mystring);
  324.       if (where!=-1)
  325.       {
  326.         strncat(dest,mystring,where);                    /* copy first part of string */
  327.         strcat(dest,to);                                 /* add repeaced chars */
  328.         strfcpy(mystring,mystring,where+strlen(from));   /* copy rest of string  so we find first position of from */
  329.       }
  330.     } while (where!=-1);                                 /* keep doing until "from" is not found */
  331.     strcat(dest,mystring);                               /* add the rest of the string */
  332.     FreeStr(mystring);
  333.   }
  334. }
  335.  
  336.  
  337. BOOL __asm __saveds GetParams(register __a0 char *dest,register __a1 char *source)
  338. {
  339.   UBYTE *strptr;
  340.  
  341.   dest[0]=0;
  342.  
  343.   if (strptr=strchr(source,'='))
  344.   {
  345.     strcpy(dest,strptr+1);
  346.  
  347.     return(TRUE);
  348.   }
  349.   return(FALSE);
  350. }
  351.  
  352. /* old version, shite...
  353. BOOL __asm __saveds GetParams(register __a0 char *dest,register __a1 char *source)
  354. {
  355.   int where;
  356.  
  357.   dest[0]=0;
  358.  
  359. //  if ( ((where=position("=",source))!=-1) && (where!=(strlen(source)-1)) )
  360.  
  361.   if ((where=position("=",source))>=0)
  362.   {
  363.     strfcpy(dest,source,where+1);
  364.     return(TRUE);
  365.   }
  366.   return(FALSE);
  367. }
  368. */
  369.  
  370.  
  371. BOOL __asm __saveds GetItem(register __a0 char *dest,register __a1 char *source)
  372. {
  373.   int loop=0;
  374.  
  375.   // increment start counter until we encounter a character that's not a space or tab
  376.  
  377.   while (source[loop]==' ' || source[loop]==8) loop++;
  378.  
  379.   while (source[loop] && source[loop]!='=') // not end of string && '=' ?
  380.   {
  381.     dest[loop]=source[loop];
  382.     loop++;
  383.   }
  384.   dest[loop]='\0';
  385.   if (dest[0]!=0) return(TRUE);
  386.  
  387.   return(FALSE);
  388. }
  389.  
  390. void __asm __saveds GetNumber(register __a0 int *num,register __a1 char *item)
  391. {
  392.   int where;
  393.   char numstr[5];
  394.   for (where=strlen(item);isdigit(item[where-1]);where--);
  395.  
  396.   strfcpy(numstr,item,where);
  397.   *num=atoi(numstr);
  398. }
  399.  
  400.  
  401. ULONG __asm __saveds  SafePutToPort(register __a0 struct Message *message, register __a1 STRPTR portname)
  402. {
  403.   struct MsgPort *port;
  404.   Forbid();
  405.   if (port=FindPort(portname))
  406.   {
  407.     PutMsg(port,message);
  408.   }
  409.   Permit();
  410.   return((ULONG)port);
  411. }
  412.  
  413. // new: if message you are sending has a reply port, it'll return a pointer to the replied
  414. // message, other wise it'll return 1.
  415. // it will ALWAYS return NULL if it fails to send the message tho..
  416.  
  417. struct Message __asm __saveds *SendMessage(register __a0 struct Message *Msg,register __a1 char *MPortName)
  418. {
  419. //  BOOL waitforreply=(Msg->mn_ReplyPort) ? TRUE : FALSE;
  420.  
  421.   if (SafePutToPort(Msg,MPortName))
  422.   {
  423. //  if (waitforreply)
  424.     if (Msg->mn_ReplyPort)
  425.     {
  426.       if (1L << Msg->mn_ReplyPort->mp_SigBit==Wait(1L << Msg->mn_ReplyPort->mp_SigBit))
  427.       {
  428.         return(GetMsg(Msg->mn_ReplyPort));
  429.       }
  430.     }
  431.     else return((struct Message *)1L);
  432.   }
  433.   return(NULL);
  434. }
  435.  
  436. V_BIGNUM __asm __saveds CountListItems( register __a0 struct List *list)
  437. {
  438.   V_BIGNUM retval=0;
  439.   struct Node *node;
  440.  
  441.   if (list)
  442.   {
  443.     for (node = list->lh_Head ; node->ln_Succ ; node =node->ln_Succ)
  444.     {
  445.       retval++;
  446.     }
  447.   }
  448.   return(retval);
  449. }
  450.  
  451. void __asm __saveds FreeStrList(register __a0 V_STRINGLIST strlist)
  452. {
  453.   // free all strings in a list and remove all nodes from the list.
  454.   // then free the nodes and the list itself..
  455.  
  456.   struct Node *node;
  457.   if (strlist)
  458.   {
  459.     while (strlist->lh_Head->ln_Succ)
  460.     {
  461.       node=strlist->lh_Head;
  462.       FreeStr(node->ln_Name);
  463.       Remove(node);
  464.       FreeVec(node);
  465.     }
  466.     FreeVec(strlist);
  467.   }
  468. }
  469.  
  470. // called by doors and the node programs to get the system data structure pointer
  471. struct BBSGlobalData __asm __saveds *HBBS_GimmeBBS( void )
  472. {
  473.   return(BBSGlobal);
  474. }
  475.  
  476. // Only the Control program can call this routine, noone else should
  477. // **EVER** call this or your system WILL crash!
  478. void __asm __saveds  HBBS_SetBBS(register __a0 struct BBSGlobalData *B)
  479. {
  480.   BBSGlobal=B;
  481. }
  482.  
  483. struct Node __asm __saveds  *GetNode(register __a0 struct List *lh,register __d0 UWORD n)
  484. { // starts from 0, 0 being the first node in the list..
  485.   // thanks to the author of YAK for this and the next function..
  486.   struct Node *ln;
  487.  
  488.   for (ln = lh->lh_Head; n--; ln = ln->ln_Succ);
  489.   return ln;
  490. }
  491.  
  492. UWORD __asm __saveds GetNodeNum(register __a0 struct List *lh,register __a1 struct Node *node)
  493. {
  494.   struct Node *ln;
  495.   UWORD i;
  496.  
  497.   for (i = 0, ln = lh->lh_Head; ln != node; ln = ln->ln_Succ, i++);
  498.   return i;
  499. }
  500.  
  501. struct NodeData __asm __saveds  *HBBS_NodeDataPtr(register __d0 short nodenum)
  502. {
  503.   struct NodeData *nd;
  504.  
  505.   for (nd = (struct NodeData *)BBSGlobal->NodeList->lh_Head ; nd->node.ln_Succ ; nd =(struct NodeData *) nd->node.ln_Succ)
  506.   {
  507.     if (nd->NodeNum==nodenum) return(nd);
  508.   }
  509.   return(NULL);
  510. }
  511.  
  512.  
  513. V_ERROR __asm __saveds HBBS_LogError(register __a0 V_STRING filename,register __d0 V_ERROR errnum,register __a1 V_STRING string,register __d1 V_ERROR errtype)
  514. {
  515.   // this function returns the parameter errnum supplied and unmodified.
  516.   BPTR FH;
  517.   V_STRING errstr;
  518.   char *strptr;
  519.   struct tm *tp;
  520.   time_t t;
  521.  
  522.   if (filename)
  523.   {
  524.     if (FH=Open(filename,MODE_READWRITE))
  525.     {
  526.       Seek(FH,0,OFFSET_END);
  527.       if (errstr=AllocVec(BIG_STR,MEMF_PUBLIC))
  528.       {
  529.         if (errnum!=ERR_INFO)
  530.         {
  531.           t=time(NULL);
  532.           tp=localtime(&t);
  533.           sprintf(errstr,"%s %s: ",asctime(tp),TYPE_STR[errtype]);
  534.  
  535.           // remove '\n's from string.
  536.  
  537.           while (strptr=strchr(errstr,'\n'))
  538.           {
  539.             errstr[strptr-errstr]=' ';
  540.           }
  541.  
  542.           Write(FH,errstr,strlen(errstr)); // don't care if it fails.. (could be diskfull :-)
  543.         }
  544.  
  545.         switch(errnum)
  546.         {
  547.           case ERR_ERROR_OPENING:
  548.             sprintf(errstr,"Error opening the file -> %s",string);
  549.             break;
  550.           case ERR_ERROR_READING:
  551.             sprintf(errstr,"Error reading the file -> %s",string);
  552.             break;
  553.           case ERR_ERROR_WRITING:
  554.             sprintf(errstr,"Error writing the file -> %s",string);
  555.             break;
  556.           case ERR_NODESETTINGS:
  557.             strcpy(errstr,"NodeLocal File Error");
  558.             break;
  559.           case ERR_GENERAL:
  560.           case ERR_INFO:
  561.             strcpy(errstr,string);
  562.             break;
  563.           case ERR_DOORTIMEOUT:
  564.             sprintf(errstr,"Timout Occured When Loading Door -> %s",string);
  565.             break;
  566.           default:
  567.             sprintf(errstr,"Unknown Error!");
  568.             break;
  569.         }
  570.         // remove '\n's from string.
  571.  
  572.         while (strptr=strchr(errstr,'\n'))
  573.         {
  574.           errstr[strptr-errstr]=' ';
  575.         }
  576.  
  577.         Write(FH,errstr,strlen(errstr));
  578.  
  579.         Write(FH,"\n",1);
  580.  
  581.         FreeVec(errstr);
  582.       }
  583.       Close(FH);
  584.     }
  585.   }
  586.   return(errnum);
  587. }
  588.  
  589. /*
  590.  
  591. // lets play spot the bug that cuases this routine to crash the system..
  592. // 5 quid goes to the person the finds the problem!!
  593.  
  594. struct CfgFileData __asm __saveds *HBBS_LoadConfig(register __a0 UBYTE *filename,register __d0 ULONG Flags)
  595. {
  596.   // New Optimized Version 04-JAN-1996
  597.  
  598.   BPTR FH;
  599.   LONG found=0;
  600.   UBYTE buffer[BIG_STR+1];
  601.   UBYTE ItemName[BIG_STR+1];
  602.   UBYTE Params[BIG_STR+1];
  603.   struct CfgFileData *cfgfile=NULL;
  604.   struct CfgItemData *node=NULL;
  605.   UBYTE infostr[BIG_STR+1];
  606.  
  607.   if (BBSGlobal->LogConfig)
  608.   {
  609.     strcpy(buffer,"Attempting to load config file: ");
  610.     strcat(buffer,filename);
  611.     HBBS_LogError(BBSGlobal->ConfigLogFile,ERR_INFO,buffer,TYPE_INFO);
  612.   }
  613.  
  614.   if (PathOK(filename))
  615.   {
  616.     // create and init our CfgFileData structure..
  617.  
  618.     if (cfgfile=AllocVec(sizeof(struct CfgFileData),MEMF_PUBLIC|MEMF_CLEAR))
  619.     {
  620.       cfgfile->filename=DupStr(filename);
  621.  
  622.       if (cfgfile->ItemsList=HBBS_CreateList())
  623.       {
  624.         if (FH=Open(filename,MODE_OLDFILE))
  625.         {
  626.           while (FGets(FH,buffer,BIG_STR))
  627.           {
  628.             stripcr(buffer);
  629.             ItemName[0]=0;
  630.             Params[0]=0;
  631.  
  632.             StripComments(buffer);
  633.  
  634.             StripSpaces(buffer);
  635.  
  636.             if (GetItem(ItemName,buffer))
  637.             {
  638.               if (GetParams(Params,buffer))
  639.               {
  640.  
  641.                 if (node=AllocVec(sizeof(struct CfgItemData),MEMF_PUBLIC))
  642.                 {
  643.                   node->node.ln_Name=DupStr(ItemName);  // *C* add errorchecking..
  644.                   node->Params=DupStr(Params);
  645.                   AddTail(cfgfile->ItemsList,(struct Node*)node);
  646.                   found++;
  647.                   if (BBSGlobal->LogConfig)
  648.                   {
  649.                     sprintf(infostr,"config item: %s %s",ItemName,Params);
  650.                     HBBS_LogError(BBSGlobal->ConfigLogFile,ERR_INFO,infostr,TYPE_INFO);
  651.                   }
  652.                 }
  653.  
  654. //                if (HBBS_AddCfgItemQuick(cfgfile,ItemName,Params))
  655. //                {
  656. //                  found++;
  657. //                }
  658.               }
  659.             }
  660.           }
  661.           Close(FH);
  662.         }
  663.       }
  664.       if (!found)
  665.       {
  666.         HBBS_FlushConfig(cfgfile);
  667.         cfgfile=NULL;
  668.       }
  669.     }
  670.   }
  671.   else
  672.   {
  673.     if (BBSGlobal->LogConfig)
  674.     {
  675.       strcpy(infostr,"Failed to find file: ");
  676.       strcat(infostr,filename);
  677.       HBBS_LogError(BBSGlobal->ConfigLogFile,ERR_INFO,infostr,TYPE_INFO);
  678.     }
  679.   }
  680.  
  681.   return(cfgfile);
  682. }
  683. */
  684.  
  685. struct CfgFileData __asm __saveds *HBBS_LoadConfig(register __a0 UBYTE *filename,register __d0 ULONG Flags)
  686. {
  687.   BPTR FH;
  688.   struct FileInfoBlock *FIB;
  689.   LONG nr;
  690.   UBYTE *Data;
  691.   ULONG Length;
  692.  
  693.   V_BOOL done,nearlydone;
  694.   LONG filepos=0,bufferpos,found=0;
  695.   V_STRING buffer;
  696.   V_STRING ItemName;
  697.   V_STRING Params;
  698.   struct CfgItemData *node;
  699.   struct CfgFileData *cfgfile=NULL;
  700.   UBYTE infostr[BIG_STR+1];
  701.  
  702.   if (BBSGlobal->LogConfig)
  703.   {
  704.     strcpy(infostr,"Attempting to load config file: ");
  705.     strcat(infostr,filename);
  706.     HBBS_LogError(BBSGlobal->ConfigLogFile,ERR_INFO,infostr,TYPE_INFO);
  707.   }
  708.  
  709.   if (FH=Open(filename,MODE_OLDFILE))
  710.   {
  711.     if (cfgfile=AllocVec(sizeof(struct CfgFileData),MEMF_PUBLIC|MEMF_CLEAR))
  712.     {
  713.  
  714.       if (FIB=(struct FileInfoBlock *)AllocVec(sizeof(struct FileInfoBlock),MEMF_PUBLIC))
  715.       {
  716.         ExamineFH(FH,FIB);
  717.         Length=FIB->fib_Size;
  718.         if (Data=AllocVec(Length,MEMF_PUBLIC))
  719.         {
  720.           if ((nr=Read(FH,Data,Length))!=Length)
  721.           {
  722.             HBBS_LogError(BBSGlobal->ErrorLogFile,ERR_ERROR_READING,filename,TYPE_CRITICAL);
  723.           }
  724.           else
  725.           {
  726.             if (cfgfile->ItemsList=HBBS_CreateList())
  727.             {
  728.               buffer=AllocVec(BIG_STR,MEMF_PUBLIC);
  729.               ItemName=AllocVec(BIG_STR,MEMF_PUBLIC);
  730.               Params=AllocVec(BIG_STR,MEMF_PUBLIC);
  731.               if (buffer && ItemName && Params)
  732.               {
  733.                 do
  734.                 {
  735.                   bufferpos=0;
  736.                   done=FALSE;
  737.                   nearlydone=FALSE; // :-) love those variable names! :-)
  738.                   do
  739.                   {
  740.                     if (Data[filepos]=='\r' || Data[filepos]=='\n')
  741.                     {
  742.                       nearlydone=TRUE;
  743.                       filepos++;
  744.                     }
  745.                     else
  746.                     {
  747.                       if (nearlydone)
  748.                       {
  749.                         done=TRUE;
  750.                       }
  751.                       else
  752.                       {
  753.                         buffer[bufferpos]=Data[filepos];
  754.                         filepos++;
  755.                         bufferpos++;
  756.                       }
  757.                     }
  758.                   } while (filepos<Length && !done && bufferpos<BIG_STR-2); // 1 for null and 1 more cos we still have to add the null
  759.                   buffer[bufferpos]=0;
  760.  
  761.                   ItemName[0]=0; // null terminate both strings..
  762.                   Params[0]=0;
  763.  
  764.                   if (!(Flags & LCFG_NOSTRIPCOMMENTS)) StripComments(buffer);
  765.                   if (!(Flags & LCFG_NOSTRIPSPACES))   StripSpaces(buffer);
  766.  
  767.                   if (GetItem(ItemName,buffer))
  768.                   {
  769.                     if (GetParams(Params,buffer))
  770.                     {
  771.                       if (node=AllocVec(sizeof(struct CfgItemData),MEMF_PUBLIC))
  772.                       {
  773.                         node->node.ln_Name=DupStr(ItemName);  // *C* add errorchecking..
  774.                         node->Params=DupStr(Params);
  775.                         AddTail(cfgfile->ItemsList,(struct Node*)node);
  776.                         found++;
  777.                         if (BBSGlobal->LogConfig)
  778.                         {
  779.                           sprintf(infostr,"Config Item: %s=%s",ItemName,Params);
  780.                           HBBS_LogError(BBSGlobal->ConfigLogFile,ERR_INFO,infostr,TYPE_INFO);
  781.                         }
  782.                       }
  783.                     }
  784.                   }
  785.                 } while (filepos<Length);
  786.               }
  787.               if (Params)     FreeVec(Params);
  788.               if (ItemName)   FreeVec(ItemName);
  789.               if (buffer)     FreeVec(buffer);
  790.             }
  791.           }
  792.           FreeVec(Data);
  793.         }
  794.         FreeVec(FIB);
  795.       }
  796.       if (found)
  797.       {
  798.         cfgfile->filename=DupStr(filename);
  799.       }
  800.       else
  801.       {
  802.         HBBS_FlushConfig(cfgfile);
  803.         cfgfile=NULL; // just to make sure.. *C* ?? needed ?
  804.       }
  805.     }
  806.     Close(FH);
  807.   }
  808.   else
  809.   {
  810.     if (BBSGlobal->LogConfig)
  811.     {
  812.       strcpy(infostr,"Failed to find file: ");
  813.       strcat(infostr,filename);
  814.       HBBS_LogError(BBSGlobal->ConfigLogFile,ERR_INFO,infostr,TYPE_INFO);
  815.     }
  816.   }
  817.   return(cfgfile);
  818. }
  819.  
  820. void  __asm __saveds  HBBS_FlushConfig(register __a0 struct CfgFileData *cfgfile)
  821. {
  822.   struct CfgItemData *node;
  823.   if (cfgfile)
  824.   {
  825.     while ((cfgfile->ItemsList) && (cfgfile->ItemsList->lh_Head->ln_Succ))
  826.     {
  827.       node=(struct CfgItemData *)cfgfile->ItemsList->lh_Head;
  828.  
  829.       FreeStr(node->node.ln_Name);
  830.       FreeStr(node->Params);
  831.       Remove((struct Node *)node);
  832.       FreeVec(node);
  833.     }
  834.     FreeVec(cfgfile->ItemsList);
  835.     FreeStr(cfgfile->filename);
  836.     FreeVec(cfgfile);
  837.   }
  838. }
  839.  
  840. V_BOOL __asm __saveds HBBS_SaveConfig(register __a0 struct CfgFileData *cfgfile)
  841. {
  842.  
  843.   // returns TRUE on successful completion.
  844.  
  845.   BPTR FH;
  846.   struct CfgItemData *node;
  847.   char outstr[BIG_STR];
  848.  
  849.   if (BBSGlobal->LogConfig)
  850.   {
  851.     strcpy(outstr,"Attempting to save config file: ");
  852.     strcat(outstr,cfgfile->filename);
  853.     HBBS_LogError(BBSGlobal->ConfigLogFile,ERR_INFO,outstr,TYPE_INFO);
  854.   }
  855.  
  856.   if (AssignOK(cfgfile->filename))
  857.   {
  858.     if (FH=Open(cfgfile->filename,MODE_NEWFILE))
  859.     {
  860.       for (node = (struct CfgItemData*)cfgfile->ItemsList->lh_Head ; node->node.ln_Succ ; node =(struct CfgItemData *)node->node.ln_Succ)
  861.       {
  862.         sprintf(outstr,"%s=%s\n",node->node.ln_Name,node->Params);
  863.         Write(FH,outstr,strlen(outstr));
  864.  
  865.         if (BBSGlobal->LogConfig)
  866.         {
  867.           sprintf(outstr,"Config item: %s=%s",node->node.ln_Name,node->Params);
  868.           HBBS_LogError(BBSGlobal->ConfigLogFile,ERR_INFO,outstr,TYPE_INFO);
  869.         }
  870.  
  871.       }
  872.       Close(FH);
  873.       return(TRUE);
  874.     }
  875.   }
  876.  
  877.   if (BBSGlobal->LogConfig)
  878.   {
  879.     strcpy(outstr,"Could not save config file: ");
  880.     strcat(outstr,cfgfile->filename);
  881.     HBBS_LogError(BBSGlobal->ConfigLogFile,ERR_INFO,outstr,TYPE_INFO);
  882.   }
  883.  
  884.   return(FALSE);
  885. }
  886.  
  887. struct CfgItemData __asm __saveds *HBBS_GetCfgNode(register __a0 struct CfgFileData *cfgfile,register __a1 V_STRING optionstr)
  888. {
  889.  
  890.   struct CfgItemData *Item;
  891.  
  892.   for (Item = (struct CfgItemData *)cfgfile->ItemsList->lh_Head ; Item->node.ln_Succ ; Item =(struct CfgItemData *) Item->node.ln_Succ)
  893.   {
  894.     if (stricmp(optionstr,Item->node.ln_Name)==0)
  895.     {
  896.       return(Item);
  897.     }
  898.   }
  899.   return(NULL);
  900. }
  901.  
  902. V_SMALLNUM __asm __saveds  HBBS_GetSetting(register __a0 struct CfgFileData *cfgfile,register __a1 void **result,register __d0 V_FLAGS optiontype,register __a2 V_STRING optionstr,register __d1 V_BOOL multi)
  903. {
  904.   // returns the amount of items found (1 for non multi, >0 for multi, 0 for none)
  905.  
  906.   V_SMALLNUM found=0;
  907.   V_STRING CompareStr;
  908.   struct Node *node;
  909.   struct CfgItemData *Item;
  910.   char outstr[BIG_STR];
  911.   char *typestr[]={"TIME","SMALLNUM","BIGNUM","STRING","BOOL","STRINGLIST","FLAGS","PATH","PATHLIST","WORD","DATE"};
  912.  
  913.   // allocate a big string for comparing the strings..
  914.   if (CompareStr=AllocVec(BIG_STR,MEMF_PUBLIC))
  915.   {
  916.     // parse list..
  917.     for (Item = (struct CfgItemData *)cfgfile->ItemsList->lh_Head ; Item->node.ln_Succ ; Item =(struct CfgItemData *) Item->node.ln_Succ)
  918.     {
  919.       if (multi==OPT_MULTI)
  920.       {
  921.         sprintf(CompareStr,"%s_%d",optionstr,found+1);
  922.       }
  923.  
  924.       if ((multi==OPT_SINGLE) && (stricmp(optionstr,Item->node.ln_Name)==0) ||
  925.          (multi==OPT_MULTI) && (stricmp(CompareStr,Item->node.ln_Name)==0))
  926.       {
  927.         switch(optiontype)
  928.         {
  929.           case VTYPE_STRING:
  930.           case VTYPE_DATE:
  931.             if (*result!=NULL) FreeStr(*result);
  932.             *result=(V_STRING *)DupStr(Item->Params);
  933.             found++;
  934.             break;
  935.           case VTYPE_PATH:
  936.             if (*result!=NULL) FreeStr(*result);
  937.             if (*result=(V_STRING)AllocVec(strlen(Item->Params)+1,MEMF_CLEAR|MEMF_PUBLIC))
  938.             {
  939.               strcpy((V_STRING)*result,Item->Params);
  940.               if ((Item->Params[strlen(Item->Params)-1]!='/') && (Item->Params[strlen(Item->Params)-1]!=':'))
  941.               {
  942.                 strcat((V_STRING)*result,"/");
  943.               }
  944.               found++;
  945.  
  946.             }
  947.             break;
  948.           case VTYPE_BOOL:
  949.             *result=(V_BOOL *)CheckBoolean(Item->Params);
  950.             found++;
  951.             break;
  952.           case VTYPE_BIGNUM:
  953.           case VTYPE_TIME:
  954.             *result=(V_BIGNUM *)atoi(Item->Params);
  955.             found++;
  956.             break;
  957.           case VTYPE_WORD:
  958.             *result=(WORD *)atoi(Item->Params);
  959.             found++;
  960.             break;
  961.           case VTYPE_SMALLNUM:
  962.             *result=(V_SMALLNUM *)atoi(Item->Params);
  963.             found++;
  964.             break;
  965.           case VTYPE_STRINGLIST:
  966.           case VTYPE_PATHLIST:
  967.             // free existing stringlist if present
  968.  
  969.             if ((found==0) && (*result))
  970.             {
  971.               FreeStrList((V_STRINGLIST)*result);
  972.             }
  973.             if (!(*result))
  974.             {
  975.               if(*result=AllocVec(sizeof (struct List),MEMF_PUBLIC))
  976.               {
  977.                 NewList((struct List*)*result);
  978.               }
  979.             }
  980.             if (*result) // allocated new list ok ?
  981.             {
  982.               if (node=AllocVec(sizeof(struct Node),MEMF_PUBLIC))
  983.               {
  984.                 if (optiontype==VTYPE_PATHLIST)
  985.                 {
  986.                   if (node->ln_Name=AllocVec(strlen(Item->Params)+2,MEMF_CLEAR|MEMF_PUBLIC)) // +1 for terminator +1 for added /
  987.                   {
  988.                     strcpy(node->ln_Name,Item->Params);
  989.                     if ((node->ln_Name[strlen(node->ln_Name)-1]!=':') && (node->ln_Name[strlen(node->ln_Name)-1]!='/'))
  990.                     {
  991.                       strcat(node->ln_Name,"/");
  992.                     }
  993.                   }
  994.                 }
  995.                 else
  996.                 {
  997.                   node->ln_Name=DupStr(Item->Params);
  998.                 }
  999.  
  1000.                 if (!(node->ln_Name))
  1001.                 {
  1002.                   FreeVec(node);
  1003.                 }
  1004.                 else
  1005.                 {
  1006.                   AddTail((struct List *)*result,node);
  1007.  
  1008.                   found++;
  1009.  
  1010.                   // go to start of list again or we might miss out something..
  1011.                   Item = (struct CfgItemData *)cfgfile->ItemsList->lh_Head;
  1012.                 }
  1013.  
  1014.               }
  1015.             }
  1016.         }
  1017.       }
  1018.     }
  1019.     FreeVec(CompareStr);
  1020.   }
  1021.  
  1022.   if (BBSGlobal->LogConfig)
  1023.   {
  1024.     sprintf(outstr,"Config Items \"%s\" type \"%s\" requested from file \"%s\". Found %d matches",optionstr,typestr[optiontype-1],cfgfile->filename,found); //-1 because array index starts at 0
  1025.     HBBS_LogError(BBSGlobal->ConfigLogFile,ERR_INFO,outstr,TYPE_INFO);
  1026.   }
  1027.  
  1028.   return(found);
  1029. }
  1030.  
  1031. struct CfgFileData __asm __saveds *HBBS_CreateConfig(register __a0 UBYTE *filename)
  1032. {
  1033.   struct CfgFileData *newcfg;
  1034.  
  1035.   if (newcfg=(struct CfgFileData *)AllocVec(sizeof(struct CfgFileData),MEMF_PUBLIC|MEMF_CLEAR))
  1036.   {
  1037.     if (newcfg->ItemsList=(struct List *)AllocVec(sizeof(struct List ),MEMF_PUBLIC))
  1038.     {
  1039.       NewList(newcfg->ItemsList);
  1040.       newcfg->filename=DupStr(filename);  // *C* add errorchecking..
  1041.     }
  1042.     else
  1043.     {
  1044.       FreeVec(newcfg);
  1045.       newcfg=NULL;
  1046.     }
  1047.   }
  1048.   return(newcfg);
  1049. }
  1050.  
  1051. BOOL __asm __saveds HBBS_RemoveCfgItem(register __a0 struct CfgFileData *cfgfile,register __a1 UBYTE *itemname)
  1052. {
  1053.   struct CfgItemData *node;
  1054.   BOOL Removed=FALSE;
  1055.   char *match;
  1056.  
  1057.   if (match=AllocVec((strlen(itemname)*2)+2,MEMF_PUBLIC))
  1058.   {
  1059.     if (cfgfile && cfgfile->ItemsList)
  1060.     {
  1061.       for (node = (struct CfgItemData*)cfgfile->ItemsList->lh_Head ;(node->node.ln_Succ) ; node =(struct CfgItemData *)node->node.ln_Succ)
  1062.       {
  1063.         ParsePatternNoCase(itemname,match,(strlen(itemname)*2)+2);
  1064.         if (MatchPatternNoCase(match,node->node.ln_Name))
  1065.         {
  1066.           Remove((struct Node*)node);
  1067.           FreeStr(node->Params);
  1068.           FreeStr(node->node.ln_Name);
  1069.           FreeVec(node);
  1070.           // go to start of list again..
  1071.           node=node = (struct CfgItemData*)cfgfile->ItemsList->lh_Head;
  1072.           Removed=TRUE;
  1073.         }
  1074.       }
  1075.     }
  1076.     FreeVec(match);
  1077.   }
  1078.   return(Removed);
  1079. }
  1080.  
  1081. BOOL __asm __saveds HBBS_AddCfgItem(register __a0 struct CfgFileData *cfgfile,register __a1 UBYTE *itemname,register __a2 UBYTE *params)
  1082. {
  1083.   struct CfgItemData *node;
  1084.   BOOL Done=FALSE;
  1085.  
  1086. /*
  1087.   char *offset,*remstr;
  1088.   short loop;
  1089. */
  1090.   if (cfgfile && cfgfile->ItemsList)
  1091.   {
  1092.     // check to see if itemname is already there..
  1093.  
  1094.     HBBS_RemoveCfgItem(cfgfile,itemname);
  1095.  
  1096. /*
  1097.  * Unsed bit of usefull code, was origonally going to make it so that when you start
  1098.  * adding items of a list to a config items list it removed all the parts of the old
  1099.  * list first..  but decided not to do it this way (at all) but left this bit of code
  1100.  * cos it might be usefull.. :-)
  1101.  *
  1102.     if (offset=strrchr(itemname,'_'))
  1103.     {
  1104.       offset++;
  1105.       if (offset[0]!=0)
  1106.       {
  1107.         if (isdigit(offset[0]))
  1108.         {
  1109.           loop=1;
  1110.           while (isdigit(offset[loop]))
  1111.           {
  1112.             loop++;
  1113.           }
  1114.  
  1115.           if (offset[loop]==0)
  1116.           {
  1117.             if (remstr=AllocVec(strlen(itemname)+2,MEMF_PUBLIC))
  1118.             {
  1119.               strNcpy(remstr,itemname,offset-itemname);
  1120.               strcat(remstr,"#?");
  1121.  
  1122.               HBBS_RemoveCfgItem(cfgfile,remstr);
  1123.  
  1124.               FreeVec(remstr);
  1125.             }
  1126.           }
  1127.         }
  1128.       }
  1129.     }
  1130. */
  1131.  
  1132.     if (node=AllocVec(sizeof(struct CfgItemData),MEMF_PUBLIC))
  1133.     {
  1134.       node->node.ln_Name=DupStr(itemname);  // *C* add errorchecking..
  1135.       node->Params=DupStr(params);
  1136.       AddTail(cfgfile->ItemsList,(struct Node*)node);
  1137.       Done=TRUE;
  1138.     }
  1139.   }
  1140.   return(Done);
  1141. }
  1142.  
  1143. void __asm __saveds HBBS_ResetNodeData(register __a0 struct NodeData *node)
  1144. {
  1145.   // this function is called a) when a node is initialised
  1146.   // and b) when a node shuts down. (everything is freed first tho..
  1147.  
  1148.   node->LoginType=LOGIN_NONE;
  1149.   node->OnlineStatus=OS_OFFLINE; // node program sets this to ONLINE or OFFLINE
  1150.                               // this shot be used in all door programs to determine
  1151.                               // carrier status (even for local logins..)
  1152.   node->User.Valid=FALSE;
  1153.   node->User.ConfAcs.Name=NULL;
  1154.   node->NodeFlags=0L;
  1155.   node->Status=STAT_CLOSED;
  1156.   node->NodePort=NULL;
  1157.   node->SettingsOpen=FALSE;
  1158.   node->InformationOpen=FALSE;
  1159.   node->ConOK=FALSE;
  1160.   node->SerOK=FALSE;
  1161.   node->SerOPEN=FALSE;
  1162.   node->SerWaiting=FALSE;
  1163.   node->ConWaiting=FALSE;
  1164.   node->ReplyPort=NULL;
  1165.   node->RequestShutdown=FALSE;
  1166.   node->ActiveDoor=NULL;
  1167.   node->DoorsRunning=0;
  1168.   node->DoorReturn[0]=0;
  1169.   node->CurrentLine[0]=0;
  1170.   node->TransferringFile=FALSE;
  1171.   node->TaggedFiles=0;
  1172.   node->AllowLogins=TRUE;
  1173.   node->DoorLogOverride=FALSE;
  1174.   node->RunningAwait=FALSE;
  1175.   strcpy(node->Action,"Initialising!"); // max 29 chars!
  1176.   node->ConnectBaud[0]=0; // max 8 chars..
  1177.  
  1178.   node->ReservedNode=FALSE;
  1179.   node->ReservedHandle[0]=0;
  1180.  
  1181.   node->Current_Last_Callers=0;
  1182.   node->Current_Last_Uploads=0;
  1183.   node->Current_Last_Downloads=0;
  1184.   node->Current_Last_PWFails=0;
  1185.   node->Current_Last_Carrier=0;
  1186.   node->Current_Last_Pagers=0;
  1187.  
  1188.   // *C* make sysop definable..
  1189.   node->Max_Last_Callers=10;
  1190.   node->Max_Last_Uploads=10;
  1191.   node->Max_Last_Downloads=10;
  1192.   node->Max_Last_PWFails=10;
  1193.   node->Max_Last_Carrier=10;
  1194.   node->Max_Last_Pagers=10;
  1195. }
  1196.  
  1197. void __asm __saveds  HBBS_rterror(register __a0 char *str)
  1198. {
  1199.   rtEZRequestTags(str,str_OK,NULL,NULL,RTGS_Flags, GSREQF_CENTERTEXT,TAG_END);
  1200. }
  1201.  
  1202.  
  1203. LONG __asm __saveds  HBBS_RunDOSCMD(register __a0 char *command,register __d0 BOOL ASYNC)
  1204. {
  1205.   LONG retval;
  1206.   char newcmd[BIG_STR],consolename[BIG_STR];
  1207.  
  1208.   static ULONG sysargs[] =
  1209.   {
  1210.     SYS_Input,NULL,
  1211.     SYS_Output,NULL,
  1212.     SYS_Asynch,TRUE,
  1213.     SYS_UserShell,TRUE,
  1214.     NP_Priority,0L,
  1215.     TAG_DONE
  1216.   };
  1217.   BPTR outputfile=NULL;
  1218.  
  1219.   sysargs[5]=ASYNC;
  1220.  
  1221.   replace(newcmd,command,"@S@",BBSGlobal->ScreenInfo.PubScreenName);
  1222.   replace(consolename,str_CONSOLE,"@S@",BBSGlobal->ScreenInfo.PubScreenName);
  1223.  
  1224. //  if (!strchr(newcmd,'>') && !strchr(newcmd,'<'))
  1225. //  {
  1226.     if (outputfile = Open(consolename,MODE_OLDFILE))
  1227.     {
  1228.       sysargs[1]=(ULONG)outputfile;
  1229.     }
  1230. //  }
  1231.   retval=SystemTagList(newcmd,(struct TagItem *)sysargs);
  1232.   if (!ASYNC && outputfile) Close(outputfile); // close window if not async
  1233.  
  1234.   return(retval);
  1235.  
  1236.   // *C* perhaps add a routine to close async'ed windows after 5 mins ??
  1237. }
  1238.  
  1239. void __asm __saveds HBBS_DoErrorMessage(register __d0 ULONG num,register __d1 ULONG node,register __a0 char *errstr)
  1240. {
  1241.   char *str;
  1242.   int len=20; // 20 extra chars should be ok for the numbers
  1243.  
  1244.   if (errstr) len+=strlen(errstr);
  1245.  
  1246.   if (str=AllocVec(len+strlen(PRG_ERRORMESSAGE),MEMF_PUBLIC))
  1247.   {
  1248.     sprintf(str,"%s %d %d ",PRG_ERRORMESSAGE,num,node);
  1249.     if (errstr) strcat(str,errstr);
  1250.     HBBS_RunDOSCMD(str,TRUE); // *C* false ?
  1251.     FreeVec(str);
  1252.   }
  1253. }
  1254.  
  1255. void __asm __saveds cvtucase(register __a0  char *str)
  1256. {
  1257.   int loop;
  1258.   for (loop=0;str[loop]!=0;loop++)
  1259.   {
  1260.     str[loop]=toupper(str[loop]);
  1261.   }
  1262. }
  1263.  
  1264. BOOL __asm __saveds AssignOK(register __a0 char *checkme )
  1265. {
  1266.   struct DosList      *DosList;
  1267.   struct DeviceNode   *DevNode;
  1268.   UBYTE           *Pointer;
  1269.   char string[32]="",cmpstring[32]="";
  1270.   int loop;
  1271.   BOOL found=FALSE;
  1272.  
  1273.   if (strNIcmp(checkme,"Progdir:",8)==0)
  1274.   {
  1275.     found=TRUE;
  1276.   }
  1277.   else
  1278.   {
  1279.  
  1280.     for (loop = 0 ; checkme[loop]!=0 && checkme[loop]!=':' && checkme[loop]!='/' ; loop++);
  1281.     strNcpy(cmpstring,checkme,loop);// +1); // +1 cos we WANT the ':'
  1282.     cvtucase(cmpstring);
  1283.     DosList = LockDosList(LDF_ALL|LDF_READ);
  1284.     while((DosList = NextDosEntry(DosList,LDF_ALL|LDF_READ)) && !found)
  1285.     {
  1286.       DevNode = (struct DeviceNode *)DosList;
  1287.  
  1288.       // assign or volume ?
  1289.       if (DevNode->dn_Type==DLT_DIRECTORY || DevNode->dn_Type==DLT_DEVICE || DevNode->dn_Type==DLT_VOLUME)
  1290.       {
  1291.         Pointer = (UBYTE *)BADDR(DevNode -> dn_Name);
  1292.         if (Pointer[0])
  1293.         {
  1294.           for(loop = 0 ; loop < Pointer[0] ; loop++)
  1295.                             string[loop] = Pointer[loop + 1];
  1296.  
  1297.           string[Pointer[0]]   = 0; /* terminate string */
  1298.   //        strcat(string,":");
  1299.           cvtucase(string);
  1300.           if (strcmp(cmpstring,string)==0) found=TRUE;
  1301.         }
  1302.       }
  1303.     }
  1304.     UnLockDosList(LDF_ALL|LDF_READ);
  1305.   }
  1306.   return(found);
  1307. }
  1308.  
  1309. BOOL __asm __saveds HBBS_InitCommon( void )
  1310. {
  1311.   SysBase = *(struct ExecBase **) 4L;
  1312.   if (DOSBase = (struct DosLibrary *) OpenLibrary ("dos.library", 0))
  1313.   {
  1314.     if (ReqToolsBase = (struct ReqToolsBase *) OpenLibrary (REQTOOLSNAME, REQTOOLSVERSION))
  1315.     return(TRUE);
  1316.   }
  1317.   return(FALSE);
  1318. }
  1319.  
  1320. void __asm __saveds HBBS_CleanUpCommon( void )
  1321. {
  1322.   if (ReqToolsBase) CloseLibrary ((struct Library *)ReqToolsBase);
  1323.   if (DOSBase) CloseLibrary ((struct Library *) DOSBase);
  1324. }
  1325.  
  1326. struct TimerData __asm __saveds *SubmitTimer(register __a0 struct TimerSetupData *TSD, register __d0 ULONG Seconds,register __d1 ULONG MicroSeconds )
  1327. {
  1328.   struct TimerData *TD=NULL;
  1329.  
  1330.   if (TSD && (Seconds || MicroSeconds))
  1331.   {
  1332.     if (TD=(struct TimerData*)AllocVec(sizeof(struct TimerData),MEMF_PUBLIC))
  1333.     {
  1334.       // copy fields accross from our blank timer IO request
  1335.       // that was initialised by InitTimer();
  1336.  
  1337.       //      Source             Dest   Size
  1338.       CopyMem(TSD->BlankTimerIO,&TD->TR,sizeof(struct timerequest));
  1339.  
  1340.       TD->TR.tr_time.tv_secs   = Seconds;
  1341.       TD->TR.tr_time.tv_micro   = MicroSeconds;
  1342.       AddHead(TSD->TimerList,(struct Node*)TD);
  1343.  
  1344.       SendIO((struct IORequest *)&TD->TR);
  1345.     }
  1346.   }
  1347.   return(TD);
  1348. }
  1349.  
  1350. void __asm __saveds AbortTimer(register __a0 struct TimerSetupData *TSD, register __a1 struct TimerData *CTD)
  1351. {
  1352.   struct TimerData *TD;
  1353.  
  1354.   if (CTD)
  1355.   {
  1356.     for (TD = (struct TimerData *)TSD->TimerList->lh_Head ; TD->node.ln_Succ ; TD =(struct TimerData *) TD->node.ln_Succ)
  1357.     {
  1358.       if (TD==CTD)
  1359.       {
  1360.         AbortIO((struct IORequest *)&CTD->TR);
  1361.         WaitIO((struct IORequest *)&CTD->TR);
  1362.         Remove((struct Node*)CTD);
  1363.         FreeVec(CTD);
  1364.         // TD is now null so we dont wat to reference it again so return from the func..
  1365.         return;
  1366.       }
  1367.     }
  1368.   }
  1369. }
  1370.  
  1371. BOOL __asm __saveds CheckTimer(register __a0 struct TimerSetupData *TSD, register __a1 struct TimerData *CTD)
  1372. {
  1373.   struct TimerData *TD;
  1374.  
  1375.   if (TSD && CTD)
  1376.   {
  1377.     for (TD = (struct TimerData *)TSD->TimerList->lh_Head ; TD->node.ln_Succ ; TD =(struct TimerData *) TD->node.ln_Succ)
  1378.     {
  1379.       if (TD==CTD)
  1380.       {
  1381.         if (CheckIO((struct IORequest *)&CTD->TR))
  1382.         {
  1383.           WaitIO((struct IORequest *)&CTD->TR);
  1384.           Remove((struct Node*)CTD);
  1385.           FreeVec(CTD);
  1386.           return(TRUE);
  1387.         }
  1388.       }
  1389.     }
  1390.   }
  1391.   return(FALSE);
  1392. }
  1393.  
  1394. void __asm __saveds CleanupTimer( register __a0 struct TimerSetupData *TSD )
  1395. {
  1396.   struct TimerData *TD;
  1397.  
  1398.   if (TSD)
  1399.   {
  1400.     if (TSD->TimerPort)
  1401.     {
  1402.       if (TSD->BlankTimerIO)
  1403.       {
  1404.         if (TSD->TimerOpen)
  1405.         {
  1406.           if (TSD->TimerList)
  1407.           {
  1408.             // remove all outstanding io requests..
  1409.             while ((struct TimerData *)TSD->TimerList->lh_Head->ln_Succ)
  1410.             {
  1411.               TD=(struct TimerData *)TSD->TimerList->lh_Head;
  1412.               AbortIO((struct IORequest *)&TD->TR);
  1413.               WaitIO((struct IORequest *)&TD->TR);
  1414.               Remove((struct Node*)TD);
  1415.               FreeVec(TD);
  1416.             }
  1417.             FreeVec(TSD->TimerList);
  1418.           }
  1419.           CloseDevice((struct IORequest *) TSD->BlankTimerIO);
  1420.           TSD->TimerOpen=FALSE;
  1421.         }
  1422.         DeleteExtIO((struct IORequest *) TSD->BlankTimerIO);
  1423.       }
  1424.       DeleteMsgPort(TSD->TimerPort);
  1425.     }
  1426.     FreeVec(TSD);
  1427.   }
  1428. }
  1429.  
  1430. struct TimerSetupData __asm __saveds *InitTimer( void )
  1431. {
  1432.   struct TimerSetupData *TSD;
  1433.  
  1434.   if (TSD=AllocVec(sizeof(struct TimerSetupData),MEMF_PUBLIC))
  1435.   {
  1436.     TSD->TimerOpen=FALSE;
  1437.     if (TSD->TimerPort = CreateMsgPort())
  1438.     {
  1439.       if (TSD->BlankTimerIO = (struct timerequest *) CreateExtIO(TSD->TimerPort,sizeof(struct timerequest)) )
  1440.       {
  1441.         if (OpenDevice( TIMERNAME, UNIT_VBLANK,(struct IORequest *) TSD->BlankTimerIO, 0L)==0) // success ?
  1442.         {
  1443.           TSD->TimerOpen=TRUE;
  1444.           TSD->BlankTimerIO->tr_node.io_Command = TR_ADDREQUEST;
  1445.           if (TSD->TimerList=AllocVec(sizeof(struct List),MEMF_PUBLIC))
  1446.           {
  1447.             NewList((struct List *)TSD->TimerList);
  1448.             return(TSD);
  1449.           }
  1450.         }
  1451.       }
  1452.     }
  1453.     CleanupTimer(TSD);
  1454.   }
  1455.   return(NULL);
  1456. }
  1457.  
  1458. BOOL __asm __saveds PathOK(register __a0 char *str)
  1459. {
  1460.   BPTR FL;
  1461.  
  1462.   if (AssignOK(str))
  1463.   {
  1464.     if (FL=Lock(str,ACCESS_READ))
  1465.     {
  1466.       UnLock(FL);
  1467.       return(TRUE);
  1468.     }
  1469.   }
  1470.   return(FALSE);
  1471. }
  1472.  
  1473. BOOL __asm __saveds  HBBS_LoadUser(register __d0 V_BIGNUM ID,register __a0 char *handle,register __a1 char *realname,register __a2 struct UserData *user)
  1474. {
  1475.   // specify only one of ID,handle or realname
  1476.   // "user" should already be allocated..
  1477.  
  1478.   BPTR FH;
  1479.   BPTR FL;
  1480.   V_BOOL Found=FALSE;
  1481.  
  1482.   if(user)
  1483.   {
  1484.     if (ID>0)
  1485.     {
  1486.       // keep trying.. *C* add error checking here to check existance of the file!
  1487.       while (!(FL=Lock(BBSGlobal->UserDataFileName,ACCESS_READ)));
  1488.       if (FH=OpenFromLock(FL))
  1489.       {
  1490.         if (Seek(FH,(ID-1)*sizeof(struct UserData),OFFSET_BEGINNING)!=-1)
  1491.         {
  1492.           if (Read(FH,user,sizeof(struct UserData))==sizeof(struct UserData))
  1493.           {
  1494.             Found=TRUE;
  1495.           }
  1496.           // else puts("Short Read!");
  1497.         }
  1498.         Close(FH);
  1499.       }
  1500.       // else puts("Error Opening Userdata file");
  1501.       if (Found) return(TRUE);
  1502.     }
  1503.     else
  1504.     {
  1505.       if (handle!=NULL) // *C* Implement!
  1506.       {
  1507. //      printf("Searching for user with a handle of %s\n",handle);
  1508.       }
  1509.       else
  1510.       {
  1511.         if (realname!=NULL) // *C* Implement!
  1512.         {
  1513. //        printf("Searching for user with a realname of %s\n",realname);
  1514.         }
  1515.       }
  1516.     }
  1517.   }
  1518.   return(FALSE);
  1519. }
  1520.  
  1521. V_BOOL __asm __saveds HBBS_ValidUserHandle(register __a0 char *userhandle, register __a1 struct UserData *FillUser)
  1522. {
  1523.  
  1524.   // Small routing to see if a user name does exist, if the user does
  1525.   // exist and FillUser points an allocated data structure the size of
  1526.   // sizeof(struct UserData) then the uses info that was found will be copied
  1527.   // to there.
  1528.  
  1529.   V_BIGNUM CurrentUserNum=0;
  1530.   V_BOOL Found=FALSE;
  1531.   struct UserData User;
  1532.  
  1533.   if (BBSGlobal->TotalUsers>=0) // spose we better check this :-)
  1534.   {
  1535.  
  1536.     // *C* change me, TotalUsers DOES NOT REFLECT amount of users in the userdata file
  1537.     // we just need a while loop that checks found and failure of HBBS_LoadUser
  1538.  
  1539.     while (!Found && CurrentUserNum<BBSGlobal->TotalUsers)
  1540.     {
  1541.       CurrentUserNum++;
  1542.       // printf("Searching %d For User \"%s\"\n",CurrentUserNum,userhandle);
  1543.       if (HBBS_LoadUser(CurrentUserNum,NULL,NULL,&User))
  1544.       {
  1545.         // *C* insert pattern matching routine here..
  1546.         // or not ?  perhps add an "Interactive Y/N" parameter.
  1547.  
  1548.         if (stricmp(userhandle,User.Handle)==0 && User.Status!='O')
  1549.         {
  1550.           Found=TRUE;
  1551.         }
  1552.       }
  1553.       // else puts("Failed To Load User");
  1554.     }
  1555.   }
  1556.   if (Found && FillUser)
  1557.   {
  1558.  
  1559.     CopyMem(&User,FillUser,sizeof (struct UserData));
  1560.   }
  1561.   return(Found);
  1562. }
  1563.  
  1564. V_BIGNUM __asm __saveds HBBS_FindTotalUsers( void )
  1565. {
  1566.   BPTR FL;
  1567.   struct FileInfoBlock FB;
  1568.  
  1569.   BBSGlobal->TotalUsers=-1;
  1570.  
  1571.   // keep trying!
  1572.  
  1573.   while (!(FL=Lock(BBSGlobal->UserDataFileName,ACCESS_READ)));
  1574.   if (Examine(FL,&FB));
  1575.   {
  1576.     BBSGlobal->TotalUsers=(V_BIGNUM)(FB.fib_Size / sizeof(struct UserData));
  1577.   }
  1578.   UnLock(FL);
  1579.  
  1580.   return(BBSGlobal->TotalUsers);
  1581. }
  1582.  
  1583. BOOL __asm __saveds LoadPrivateData( void )
  1584. {
  1585.   struct CfgFileData *PrivateCFG;
  1586.   BOOL retval=FALSE;
  1587.  
  1588.   if (PrivateCFG=HBBS_LoadConfig(FILE_PRIVATEDATA,LCFG_NONE))
  1589.   {
  1590.     HBBS_GetSetting(PrivateCFG,(void *)&BBSGlobal->CallsEver,VTYPE_BIGNUM,OPT_PRIV_CallsEver,OPT_SINGLE);
  1591.     if (HBBS_GetSetting(PrivateCFG,(void *)&BBSGlobal->LastUserNum,VTYPE_BIGNUM,OPT_PRIV_LastUserNum,OPT_SINGLE))
  1592.     {
  1593.       retval=TRUE;
  1594.     }
  1595.     HBBS_FlushConfig(PrivateCFG);
  1596.   }
  1597.  
  1598.   return(retval);
  1599. }
  1600.  
  1601. void __asm __saveds UpdatePrivateData ( void )
  1602. {
  1603.   struct CfgFileData *PrivateCFG;
  1604.   char str[BIG_STR];
  1605.  
  1606.   if (PrivateCFG=HBBS_CreateConfig(FILE_PRIVATEDATA))
  1607.   {
  1608.     sprintf(str,"%ld",BBSGlobal->CallsEver);
  1609.     HBBS_AddCfgItemQuick(PrivateCFG,OPT_PRIV_CallsEver,str);
  1610.  
  1611.     sprintf(str,"%ld",BBSGlobal->LastUserNum);
  1612.     HBBS_AddCfgItemQuick(PrivateCFG,OPT_PRIV_LastUserNum,str);
  1613.  
  1614.     HBBS_SaveConfig(PrivateCFG);
  1615.     HBBS_FlushConfig(PrivateCFG);
  1616.   }
  1617. }
  1618.  
  1619. BOOL __asm __saveds HBBS_AddUser(register __a0 struct UserData *user)
  1620. {
  1621.   // *C* need to add some checking/locking of file for multinode operation..
  1622.  
  1623.   BPTR FH;
  1624.   BPTR FL;
  1625.  
  1626.   BOOL Saved=FALSE;
  1627.   char dirname[BIG_STR],filenote[80];
  1628.  
  1629.   // *C* need to check to see if file exists... (or get setup program to create..)
  1630.  
  1631.   // get exclusive access to userdata file when writing..
  1632.  
  1633.   while (!(FL=Lock(BBSGlobal->UserDataFileName,ACCESS_WRITE))); // keep trying..
  1634.  
  1635.   if (FH=OpenFromLock(FL)) //(BBSGlobal->UserDataFileName,MODE_OLDFILE))
  1636.   {
  1637.     if (Seek(FH,0,OFFSET_END)!=-1)
  1638.     {
  1639.       BBSGlobal->LastUserNum++;
  1640.       user->UserID=BBSGlobal->LastUserNum;
  1641.       if (Write(FH,user,sizeof(struct UserData))==sizeof(struct UserData))
  1642.       {
  1643.         UpdatePrivateData();
  1644.  
  1645.  
  1646.         Saved=TRUE;
  1647.       }
  1648.       else
  1649.       {
  1650.         // puts("Error Adding Data To File, Truncating..");
  1651.         if (SetFileSize(FH,OFFSET_BEGINNING,BBSGlobal->TotalUsers * sizeof(struct UserData))==-1)
  1652.         {
  1653.           // puts("Cound Not Truncate File!");
  1654.         }
  1655.       }
  1656.     } // else puts("Seek() Failed!");
  1657.     Close(FH);
  1658.   }
  1659.   else UnLock(FL);
  1660.  
  1661.   if (Saved)
  1662.   {
  1663.     sprintf(filenote,"Handle: %s, Group: %s",user->Handle, user->Group);
  1664.  
  1665.     sprintf(dirname,"HBBS:System/Data/Users/%d",user->UserID);
  1666.     if (FL=CreateDir(dirname))
  1667.     {
  1668.       UnLock(FL);
  1669.       SetComment(dirname,filenote);
  1670.     }
  1671.  
  1672.     sprintf(dirname,"HBBS:Mail/Users/%d",user->UserID);
  1673.     if (FL=CreateDir(dirname))
  1674.     {
  1675.       UnLock(FL);
  1676.       SetComment(dirname,filenote);
  1677.     }
  1678.   }
  1679.  
  1680.   HBBS_FindTotalUsers();
  1681.   return(Saved);
  1682. }
  1683.  
  1684. struct Node __asm __saveds *HBBS_FindNode(register __a0 struct List *list,register __a1 char *str)
  1685. {
  1686.   struct Node *node,*retval=NULL;
  1687.   V_BOOL found=FALSE;
  1688.  
  1689.   if (list && str)
  1690.   {
  1691.     for (node=list->lh_Head;!found && node->ln_Succ;node=node->ln_Succ)
  1692.     {
  1693.       if (node->ln_Name)
  1694.       {
  1695.         if (stricmp(node->ln_Name,str)==0)
  1696.         {
  1697.           found=TRUE;
  1698.           retval=node;
  1699.         }
  1700.       }
  1701.     }
  1702.   }
  1703.   return(retval);
  1704. }
  1705.  
  1706. V_BIGNUM __asm __saveds HBBS_FindNodeNum(register __a0 struct List *list, register __a1 char *str)
  1707. {
  1708.   struct Node *node;
  1709.   V_BIGNUM retval=-1;
  1710.   if (node=HBBS_FindNode(list,str))
  1711.   {
  1712.     retval=GetNodeNum(list,node);
  1713.   }
  1714.   return(retval);
  1715. }
  1716.  
  1717. void __asm __saveds HBBS_InitUserData(register __a0 struct UserData *User,register __d0 V_BIGNUM AccessLevel,register __d1 V_BIGNUM ConfNum)
  1718. {
  1719.   struct Node *node;
  1720.   char tmpstr[BIG_STR];
  1721.   int num;
  1722.  
  1723.   User->Status=USER_NEW;
  1724.   User->Access=AccessLevel;
  1725.   User->Handle[0]=0;
  1726.   User->RealName[0]=0;
  1727.   User->Group[0]=0;
  1728.   User->GeoLocation[0]=0;
  1729.   User->Country[0]=0;
  1730.   User->PhoneNumber[0]=0;
  1731.   User->Password[0]=0;
  1732.   User->ComputerType[0]=0;
  1733.   User->SentBy[0]=0;
  1734.  
  1735.   User->ConfAcsDataFile[0]=0;
  1736.  
  1737.   sprintf(tmpstr,"%d",AccessLevel);
  1738.   if ((num=HBBS_FindNodeNum(BBSGlobal->AcsLevelList,tmpstr))!=-1)
  1739.   {
  1740.     node=GetNode(BBSGlobal->AcsLevelConfAcsDef,num);
  1741.     strcpy(User->ConfAcsDataFile,node->ln_Name);
  1742.   }
  1743.   User->LeechAccDataFile[0]=0;
  1744.   User->UploadBytes=0;
  1745.   User->UploadFiles=0;
  1746.   User->DownloadBytes=0;
  1747.   User->DownloadFiles=0;
  1748.   User->ActualUploadBytes=0;
  1749.   User->ActualUploadFiles=0;
  1750.   User->ActualDownloadBytes=0;
  1751.   User->ActualDownloadFiles=0;
  1752.   User->LastUploadDate=0; // *C* add HBBS_Todate() ?
  1753.   User->LastCalledDate=0;
  1754.   User->BestCPSUp=0;
  1755.   User->BestCPSDown=0;
  1756.   User->CallsMade=0;
  1757.   User->PagesMade=0;
  1758.   User->MessagesWritten=0;
  1759.   User->FilesRatio=3;
  1760.   User->BytesRatio=3;
  1761.   User->LastConf=ConfNum;
  1762.   User->PreferedConf=0;
  1763.   User->LinesPerScreen=24;
  1764.   User->Protocol=0; // ASK
  1765.   User->Editor=0; // ASK
  1766.   User->TimeAccessFile[0]=0;
  1767.   User->ExtraTimeLimit=0;
  1768.   User->ExtraBytesLimit=0;
  1769.   User->ExtraCallsLimit=0;
  1770.   User->ExtraChatLimit=0;
  1771.   User->TimeUsed=0;
  1772.   User->BytesUsed=0;
  1773.   User->CallsUsed=0;
  1774.   User->ChatUsed=0;
  1775.   User->BytesAllowed=0;
  1776.   User->TimeAllowed=0;
  1777.   User->CallsAllowed=0;
  1778.   User->ChatAllowed=0;
  1779.   User->UserType=USERTYPE_NORMAL;
  1780.   User->Language=0; // .TXT or the first one in the list..
  1781. }
  1782.  
  1783. void __asm __saveds strNcpy(register __a0 UBYTE *dest,register __a1 UBYTE *source,register __d0 int chars)
  1784. {
  1785.   int count=0;
  1786.  
  1787.   while ((dest[count]=source[count]) && count<chars-1) count++;
  1788.   dest[count+1]=0;
  1789. }
  1790.  
  1791. char __asm __saveds *HBBS_ListName(register __a0 V_STRINGLIST ListName,register __d0 V_SMALLNUM ItemNum)
  1792. { //starts from offset 0, 0 being the first node in the list..
  1793.   struct Node *node;
  1794.  
  1795.   if(node=GetNode(ListName,ItemNum))
  1796.   {
  1797.     return(node->ln_Name);
  1798.   }
  1799.   return(NULL);
  1800. }
  1801.  
  1802. void __asm __saveds FreeFileTags( register __a0 struct NodeData *N_ND )
  1803. {
  1804.   struct TaggedFile *tfnode;
  1805.   while ((N_ND->TaggedFileList) && (N_ND->TaggedFileList->lh_Head->ln_Succ))
  1806.   {
  1807.     tfnode=(struct TaggedFile *)N_ND->TaggedFileList->lh_Head;
  1808.     FreeStr(tfnode->node.ln_Name);
  1809.     Remove((struct Node*)tfnode);
  1810.     FreeVec(tfnode);
  1811.   }
  1812.   N_ND->TaggedFiles=0;
  1813. }
  1814.  
  1815. /*
  1816.  
  1817.  
  1818. struct List __asm __saveds *HBBS_LoadFile(register __a0 char *filename)
  1819. {
  1820.   BPTR FL,FH;
  1821.   LONG bufferpos;
  1822.   BOOL done;
  1823.   struct FileInfoBlock FB;
  1824.   UBYTE *Data=NULL;
  1825.   LONG Length=0,filepos=0;
  1826.   UBYTE buffer[bufflen];
  1827.   struct List *FileList=NULL;
  1828.  
  1829.   if (FL=Lock(filename,ACCESS_READ))
  1830.   {
  1831.     if (Examine(FL,&FB))
  1832.     {
  1833.       if (FB.fib_Size)
  1834.       {
  1835.         if (Data=AllocVec(FB.fib_Size,MEMF_PUBLIC))
  1836.         {
  1837.           if (FH=OpenFromLock(FL))
  1838.           {
  1839.             Length=Read(FH,Data,FB.fib_Size);
  1840.             Close(FH);
  1841.           }
  1842.         }
  1843.       }
  1844.     }
  1845.     UnLock(FL);
  1846.  
  1847.     if ((Data) && (Length>0))
  1848.     {
  1849.       if (FileList=HBBS_CreateList())
  1850.       {
  1851.  
  1852.         do
  1853.         {
  1854.           bufferpos=0;
  1855.           done=FALSE;
  1856.           do
  1857.           {
  1858.  
  1859.             if (Data[filepos]==13) //cr
  1860.             {
  1861.               if ((filepos+1<Length) && (Data[filepos+1]==10)) // cr followed by lf ?
  1862.               {
  1863.                 done=TRUE;
  1864.                 filepos++;//skip the lf too.
  1865.               }
  1866.               else
  1867.               {
  1868.                 done=TRUE;
  1869.               }
  1870.               filepos++; //skip the cr
  1871.             }
  1872.             else
  1873.             {
  1874.               if (Data[filepos]==10) //lf
  1875.               {
  1876.                 done=TRUE;
  1877.                 filepos++;
  1878.               }
  1879.               else
  1880.               {
  1881.                 buffer[bufferpos]=Data[filepos];
  1882.                 filepos++;
  1883.                 bufferpos++;
  1884.               }
  1885.             }
  1886.           } while (filepos<Length && !done && bufferpos<bufflen-2); // 1 for null and 1 more cos we still have to add the null
  1887.           buffer[bufferpos]=0;
  1888.  
  1889.           NewStrNode(buffer,FileList);
  1890.  
  1891.         } while (filepos<Length);
  1892.       }
  1893.     }
  1894.     if (Data) FreeVec(Data);
  1895.   }
  1896.   return(FileList);
  1897. }
  1898. */
  1899.  
  1900.  
  1901. #define bufflen 1024
  1902.  
  1903. struct List __asm __saveds *HBBS_LoadFile(register __a0 char *filename)
  1904. {
  1905.   /* New Optimized Version: 4-JAN-1996 */
  1906.  
  1907.   BPTR FH;
  1908.   UBYTE buffer[bufflen];
  1909.   struct List *FileList=NULL;
  1910.   BOOL error=FALSE;
  1911.  
  1912.   if (PathOK(filename))
  1913.   {
  1914.     if (FH=Open(filename,MODE_OLDFILE))
  1915.     {
  1916.       if (FileList=HBBS_CreateList())
  1917.       {
  1918.         while (FGets(FH,buffer,bufflen) && !error)
  1919.         {
  1920.           stripcr(buffer);
  1921.           if (NewStrNode(buffer,FileList))
  1922.           {
  1923.             error=TRUE;
  1924.           }
  1925.         }
  1926.       }
  1927.       Close(FH);
  1928.     }
  1929.   }
  1930.   if (error)
  1931.   {
  1932.     FreeStrList(FileList);
  1933.     FileList=NULL;
  1934.   }
  1935.   return(FileList);
  1936. }
  1937.  
  1938.  
  1939. BOOL __asm __saveds HBBS_SaveFile( register __a0 char *file_name, register __a1 struct List *list)
  1940. {
  1941.   BPTR FH;
  1942.   struct Node *node;
  1943.  
  1944.   if (FH=Open(file_name,MODE_NEWFILE))
  1945.   {
  1946.     if (list)
  1947.     {
  1948.       for (node = list->lh_Head ; node->ln_Succ ; node =node->ln_Succ)
  1949.       {
  1950.         Write(FH,node->ln_Name,strlen(node->ln_Name));
  1951.         Write(FH,"\n",1); //add cr+lf
  1952.       }
  1953.     }
  1954.     Close(FH);
  1955.   }
  1956.   return((BOOL)(FH ? TRUE : FALSE));
  1957. }
  1958.  
  1959. struct List __asm __saveds *HBBS_CreateList( void )
  1960. {
  1961.   struct List *NList;
  1962.   if (NList=AllocVec(sizeof(struct List),MEMF_PUBLIC))
  1963.   {
  1964.     NewList(NList);
  1965.   }
  1966.   return(NList);
  1967. }
  1968.  
  1969. void __asm __saveds strftcpy(register __a0 char *dest,register __a1 char *source,register __d0 int from,register __d1 int topos)
  1970. {
  1971.   int loop=from,pos=0;
  1972.   if (from<=strlen(source)-1)
  1973.   {
  1974.     while (source[loop] && loop<=topos)
  1975.     {
  1976.       dest[pos]=source[loop];
  1977.       loop++;
  1978.       pos++;
  1979.     }
  1980.   }
  1981.   dest[pos]=0;
  1982. }
  1983.  
  1984. void __asm __saveds RemoveSpaces(register __a0 char *string)
  1985. {
  1986.   // removes spaces from the start end end of strings
  1987.   ULONG start,end,len;
  1988.  
  1989.   if (string)
  1990.   {
  1991.     len=strlen(string);
  1992.     for (start=0;string[start]==' ';start++);
  1993.     for (end=len-1;string[end]==' ';end--);
  1994.     strftcpy(string,string,start,end);
  1995.   }
  1996. }
  1997.  
  1998.  
  1999. void __asm __saveds HBBS_SaveUserData(register __a0 struct UserData *User)
  2000. {
  2001.   // *C* here we should save the data in N_ND->User.NormalData
  2002.   // back to the user file..
  2003.  
  2004.   BPTR FH,FL;
  2005.   BOOL Found,ReadError=FALSE;
  2006.   struct UserData OldUser;
  2007.  
  2008.   while (!(FL=Lock(BBSGlobal->UserDataFileName,ACCESS_WRITE)));
  2009.   if (FH=OpenFromLock(FL))
  2010.   {
  2011.     Found=FALSE;
  2012.     while (!Found && !ReadError)
  2013.     {
  2014.       // keep going until the end of the file or we get a read error..
  2015.       ReadError=((Read(FH,&OldUser,sizeof(struct UserData))==sizeof(struct UserData)) ? FALSE : TRUE );
  2016.  
  2017.       if (!ReadError)
  2018.       {
  2019.         if (OldUser.UserID==User->UserID)
  2020.         {
  2021.           Found=TRUE;
  2022.         }
  2023.       }
  2024.     }
  2025.     if (Found)
  2026.     {
  2027.       // *C* if error on next to commands then loop until it works ?
  2028.  
  2029.       // seek to start of record.
  2030.       Seek(FH,0-sizeof(struct UserData),OFFSET_CURRENT);
  2031.       Write(FH,User,sizeof(struct UserData));
  2032.     }
  2033.     Close(FH);
  2034.   }
  2035.   else UnLock(FL);
  2036. }
  2037.  
  2038. void __asm __saveds HBBS_GetDate(register __a0 char *datestr)
  2039. {
  2040.   struct tm *timestruct;
  2041.   time_t t;
  2042.   if (datestr)
  2043.   {
  2044.     t=time(NULL);
  2045.     timestruct=localtime(&t);
  2046.  
  2047.     HBBS_DateStrFromTM(datestr,timestruct);
  2048.  
  2049. /*
  2050.     sprintf(datestr,"%s%d-%s-%-04d",(timestruct->tm_mday < 10) ? "0" : "",timestruct->tm_mday,monthstr[timestruct->tm_mon],timestruct->tm_year + 1900);
  2051. */
  2052.   }
  2053.   free(timestruct);
  2054. }
  2055.  
  2056. V_BOOL __asm __saveds HBBS_AddCfgItemQuick(register __a0 struct CfgFileData *cfgfile,register __a1 char *ItemName, register __a2 char *Params)
  2057. {
  2058.   struct CfgItemData *node;
  2059.   V_BOOL retval=FALSE;
  2060.  
  2061.   if (cfgfile && ItemName && Params)
  2062.   {
  2063.     if (node=AllocVec(sizeof(struct CfgItemData),MEMF_PUBLIC))
  2064.     {
  2065.       node->node.ln_Name=DupStr(ItemName);     // *C* error check me! (or not ?)
  2066.       node->Params=DupStr(Params);
  2067.       AddTail(cfgfile->ItemsList,(struct Node*)node);
  2068.       retval=TRUE;
  2069.     }
  2070.   }
  2071.   return(retval);
  2072. }
  2073.  
  2074. void __asm __saveds HBBS_SaveCallsData( void )
  2075. {
  2076.   struct CfgFileData *CfgFile;
  2077.   struct NodeData *nd;
  2078.   UBYTE tmpstr[200],optionstr[200];
  2079.  
  2080.  
  2081.   if (CfgFile=HBBS_CreateConfig("HBBS:System/Data/Calls.CFG"))
  2082.   {
  2083.     HBBS_GetDate(tmpstr);
  2084.     HBBS_AddCfgItemQuick(CfgFile,"Today",tmpstr);
  2085.  
  2086.     sprintf(tmpstr,"%d",BBSGlobal->CallsToday);
  2087.     HBBS_AddCfgItemQuick(CfgFile,"TotalCalls",tmpstr);
  2088.  
  2089.     for (nd=(struct NodeData *)BBSGlobal->NodeList->lh_Head;nd->node.ln_Succ;nd=(struct NodeData *)nd->node.ln_Succ)
  2090.     {
  2091.       sprintf(optionstr,"Node_%d_Calls",nd->NodeNum);
  2092.       sprintf(tmpstr,"%d",nd->CallsToday);
  2093.       HBBS_AddCfgItemQuick(CfgFile,optionstr,tmpstr);
  2094.     }
  2095.     HBBS_SaveConfig(CfgFile);
  2096.     HBBS_FlushConfig(CfgFile);
  2097.   }
  2098.  
  2099. }
  2100.  
  2101. void __asm __saveds HBBS_LoadCallsData( void )
  2102. {
  2103.   struct CfgFileData *CfgFile;
  2104.   BOOL Loaded=FALSE;
  2105.   V_STRING TodayStr=NULL;
  2106.   UBYTE tmpstr[200];
  2107.   struct NodeData *nd;
  2108.  
  2109.   HBBS_GetDate(tmpstr);
  2110.  
  2111.   if (CfgFile=HBBS_LoadConfig("HBBS:System/Data/Calls.CFG",LCFG_NONE))
  2112.   {
  2113.     if (HBBS_GetSetting(CfgFile,(void *)&TodayStr,VTYPE_STRING,"Today",OPT_SINGLE))
  2114.     {
  2115.       if (stricmp(TodayStr,tmpstr)==0) // same day ???
  2116.       {
  2117.         if (HBBS_GetSetting(CfgFile,(void *)&BBSGlobal->CallsToday,VTYPE_BIGNUM,"TotalCalls",OPT_SINGLE))
  2118.         {
  2119.           for (nd=(struct NodeData *)BBSGlobal->NodeList->lh_Head;nd->node.ln_Succ;nd=(struct NodeData *)nd->node.ln_Succ)
  2120.           {
  2121.             sprintf(tmpstr,"Node_%d_Calls",nd->NodeNum);
  2122.             if (!HBBS_GetSetting(CfgFile,(void *)&nd->CallsToday,VTYPE_BIGNUM,tmpstr,OPT_SINGLE))
  2123.             {
  2124.               nd->CallsToday=0;
  2125.             }
  2126.           }
  2127.           Loaded=TRUE;
  2128.         }
  2129.       }
  2130.     }
  2131.   }
  2132.   if (!Loaded)
  2133.   {
  2134.     BBSGlobal->CallsToday=0;
  2135.  
  2136.     for (nd=(struct NodeData *)BBSGlobal->NodeList->lh_Head;nd->node.ln_Succ;nd=(struct NodeData *)nd->node.ln_Succ)
  2137.     {
  2138.       nd->CallsToday=0;
  2139.     }
  2140.     HBBS_SaveCallsData();
  2141.   }
  2142.   if (TodayStr) FreeStr(TodayStr);
  2143. }
  2144.  
  2145. void __asm __saveds HBBS_GetTime(register __a0 char *timestr)
  2146. {
  2147.   struct tm *timestruct;
  2148.   time_t t;
  2149.  
  2150.   if (timestr)
  2151.   {
  2152.     t=time(NULL);
  2153.     timestruct=localtime(&t);
  2154.  
  2155.     sprintf(timestr,"%s%d:%s%d:%s%d",(timestruct->tm_hour < 10) ? "0" : "",timestruct->tm_hour,
  2156.                                      (timestruct->tm_min < 10) ? "0" : "",timestruct->tm_min,
  2157.                                      (timestruct->tm_sec < 10) ? "0" : "",timestruct->tm_sec);
  2158.   }
  2159.   free(timestruct);
  2160. }
  2161.  
  2162. void __asm __saveds HBBS_GetDateStr(register __a0 char *datestr,register __d0 time_t t)
  2163. {
  2164.   time_t tt=t;
  2165.   struct tm *timestruct;
  2166.   if (datestr)
  2167.   {
  2168.     timestruct=localtime(&tt);
  2169.  
  2170. /*
  2171.     if (timestruct->tm_mday<0)
  2172.     {
  2173.       strcpy(datestr,"01-JAN-1970"); // date limit!
  2174.     }
  2175.     else
  2176.     {
  2177.       sprintf(datestr,"%s%d-%s-%-04d",(timestruct->tm_mday < 10) ? "0" : "",timestruct->tm_mday,monthstr[timestruct->tm_mon],timestruct->tm_year+1900);
  2178.     }
  2179. */
  2180.     HBBS_DateStrFromTM(datestr,timestruct);
  2181.     free(timestruct);
  2182.   }
  2183. }
  2184.  
  2185. void __asm __saveds HBBS_DateStrFromTM(register __a0 UBYTE *datestr, register __a1 struct tm *timestruct)
  2186. {
  2187.   if (datestr && timestruct)
  2188.   {
  2189.     if (timestruct->tm_mday<0)
  2190.     {
  2191.       strcpy(datestr,"01-JAN-1970"); // date limit!
  2192.     }
  2193.     else
  2194.     {
  2195.       sprintf(datestr,"%s%d-%s-%-04d",(timestruct->tm_mday < 10) ? "0" : "",timestruct->tm_mday,monthstr[timestruct->tm_mon],timestruct->tm_year+1900);
  2196.     }
  2197.   }
  2198.  
  2199. }
  2200.  
  2201. V_BOOL __asm __saveds  HBBS_DateStrToTM(register __a0 UBYTE *datestr, register __a1 struct tm *timestruct)
  2202. {
  2203.   UBYTE tmpstr[5];
  2204.   LONG tday,tmon=-1,tyear,loop;
  2205.  
  2206.   strNcpy(tmpstr,datestr,2);
  2207.   if (sscanf(tmpstr,"%ld",&tday))
  2208.   {
  2209.     strftcpy(tmpstr,datestr,3,5);
  2210.     for (loop=0;loop<=12 && tmon==-1;loop++)
  2211.     {
  2212.       if (stricmp(tmpstr,monthstr[loop])==0)
  2213.       {
  2214.         tmon=loop;
  2215.       }
  2216.     }
  2217.     if (tmon>=0)
  2218.     {
  2219.       strftcpy(tmpstr,datestr,7,10);
  2220.       if (sscanf(tmpstr,"%ld",&
  2221.       tyear))
  2222.       {
  2223.         tyear-=1900;
  2224.         if ((tyear>=70) && (tmon>=0) && (tmon<12) && (tday>=1) && (tday<=31))
  2225.         {
  2226.           // all data is ok, so opy it to the timestruct!
  2227.           timestruct->tm_mday=tday;
  2228.           timestruct->tm_year=tyear;
  2229.           timestruct->tm_mon=tmon;
  2230.           return(TRUE);
  2231.         }
  2232.       }
  2233.     }
  2234.   }
  2235.   return(FALSE);
  2236. }
  2237.  
  2238. // private function
  2239. void *AllocBuffer(ULONG *BufferSize,ULONG Flags) // min 10 bytes!
  2240. {
  2241.   void *retval=NULL;
  2242.  
  2243.   if (*BufferSize)
  2244.   {
  2245.     if (*BufferSize<10) *BufferSize=10;
  2246.     while ((*BufferSize>10) && ((retval=AllocVec(*BufferSize,Flags))==NULL))
  2247.     {
  2248.       *BufferSize/=2; // divide buffersize by 2!
  2249.     }
  2250.  
  2251.   }
  2252.   return(retval);
  2253. }
  2254.  
  2255. V_BOOL __asm __saveds HBBS_CopyFile(register __a0 char *fromfile, register __a1 char *tofile,register __d0 ULONG BufSize)
  2256. {
  2257.   BOOL retval=FALSE;
  2258.   BPTR FL,FromFH,ToFH;
  2259.   struct FileInfoBlock FB;
  2260.   BOOL error=TRUE;
  2261.   ULONG nr,nw,total=0;
  2262.   UBYTE *Buffer;
  2263.   ULONG MyBufSize=BufSize;
  2264.  
  2265.   if (MyBufSize==0) MyBufSize=BBSGlobal->CopyBufferSize; // *C* user selectable!
  2266.  
  2267.   if (FL=Lock(fromfile,ACCESS_READ))
  2268.   {
  2269.     if (Examine(FL,&FB))
  2270.     {
  2271.       if (FromFH=OpenFromLock(FL))
  2272.       {
  2273.         if (ToFH=Open(tofile,MODE_NEWFILE))
  2274.         {
  2275.           if (FB.fib_Size>0)
  2276.           {
  2277.             if (MyBufSize>FB.fib_Size) MyBufSize=FB.fib_Size; // no sense allocating to much mem
  2278.             if (Buffer=AllocBuffer(&MyBufSize,MEMF_PUBLIC))
  2279.             {
  2280.               do
  2281.               {
  2282.                 error=FALSE;
  2283.                 if (nr=Read(FromFH,Buffer,MyBufSize-1))
  2284.                 {
  2285.                   if (nr==(nw=Write(ToFH,Buffer,nr)))
  2286.                   {
  2287.                     total+=nw;
  2288.                   } else error=TRUE;
  2289.                 } else error=TRUE;
  2290.               } while (!error);
  2291.               if (error && total>=FB.fib_Size) error=FALSE; //end of file rather than error...
  2292.  
  2293.               FreeVec(Buffer);
  2294.             }
  2295.           }
  2296.           else
  2297.           {
  2298.             error=FALSE;
  2299.           }
  2300.           Close(ToFH);
  2301.           SetComment(tofile,FB.fib_Comment);
  2302.           SetProtection(tofile,FB.fib_Protection);
  2303.         }
  2304.         Close(FromFH);
  2305.         FL=NULL;
  2306.       }
  2307.     }
  2308.     if (FL) UnLock(FL);
  2309.   }
  2310.   if (!error)
  2311.   {
  2312.     retval=TRUE;
  2313. //    if (FL=Lock(tofile,ACCESS_READ)) // is the new file the same as the old one ?
  2314. //    {
  2315. //      total=FB.fib_Size;
  2316. //      if (Examine(FL,&FB) && total==FB.fib_Size) retval=TRUE;
  2317. //      UnLock(FL);
  2318. //    }
  2319.   }
  2320.  
  2321.   if (!retval) // if the old file is different then delete it..
  2322.   {
  2323.     DeleteFile(tofile);
  2324.   }
  2325.   return(retval);
  2326. }
  2327.  
  2328. ULONG __asm __saveds HBBS_NodesInList(register __a0 struct List *list)
  2329. {
  2330.   struct Node *node;
  2331.   ULONG Nodes=0;
  2332.   if (list)
  2333.   {
  2334.     for (node=list->lh_Head;node->ln_Succ;node=node->ln_Succ)
  2335.     {
  2336.       Nodes++;
  2337.     }
  2338.     return(Nodes);
  2339.   }
  2340.   return(0);
  2341. }
  2342.  
  2343. V_BOOL __asm __saveds HBBS_AppendStrToFile(register __a0 UBYTE *FileName, register __a1 UBYTE *String)
  2344. {
  2345.   BPTR FH;
  2346.   V_BOOL retval=FALSE;
  2347.  
  2348.   if (AssignOK(FileName))
  2349.   {
  2350.     if (FH=Open(FileName,MODE_READWRITE))
  2351.     {
  2352.       Seek(FH,0,OFFSET_END);
  2353.       if (Write(FH,String,strlen(String))==strlen(String)) retval=TRUE;
  2354.  
  2355.       Close(FH);
  2356.     }
  2357.   }
  2358.   return(retval);
  2359. }
  2360.  
  2361.  
  2362. /*
  2363.    HBBS_CreateNode() creates a node and returns a pointer to it.
  2364.  
  2365.    if namestr is not NULL then the a new string will be allocated and
  2366.    placed the ln_Name field.
  2367.  
  2368.    if you specify 0 for the nodesize, then the size of the node allocated
  2369.    will be the sizeof(struct Node), otherwise it'll allocate however many bytes
  2370.    you specify.
  2371.  
  2372.    All the data will be zero'd, so all your other fields will be intialized to NULL
  2373.    or 0!
  2374.  
  2375. */
  2376.  
  2377. struct Node __asm __saveds *HBBS_CreateNode(register __a0 char *namestr,register __d0 ULONG nodesize)
  2378. {
  2379.   struct Node *newnode;
  2380.  
  2381.   if (nodesize==0) nodesize=sizeof(struct Node);
  2382.  
  2383.   if (newnode=AllocVec(nodesize,MEMF_CLEAR|MEMF_PUBLIC))
  2384.   {
  2385.     if (namestr)
  2386.     {
  2387.       if (!(newnode->ln_Name=DupStr(namestr)))
  2388.       {
  2389.         FreeVec(newnode);
  2390.         newnode=NULL; // failed!
  2391.       }
  2392.     }
  2393.   }
  2394.   return(newnode);  // NULL if not enough mem, or pointer to node otherwise..
  2395. }
  2396.  
  2397. void __asm __saveds HBBS_FreeNode(register __a0 struct Node *node,register __d0 V_BOOL RemoveIt)
  2398. {
  2399.   if (node)
  2400.   {
  2401.     if (RemoveIt) Remove(node);
  2402.     if (node->ln_Name) FreeStr(node->ln_Name);
  2403.     FreeVec(node);
  2404.   }
  2405. }
  2406.  
  2407. void __asm __saveds HBBS_FreeListNodes(register __a0 struct List *list)
  2408. {
  2409.   // free all ln_Names of each node in a list and remove all nodes from the list!
  2410.   // but we DON't free the list itself, we just leave it empty
  2411.  
  2412.   struct Node *node;
  2413.   if (list)
  2414.   {
  2415.     while (list->lh_Head->ln_Succ)
  2416.     {
  2417.       node=list->lh_Head;
  2418.       FreeStr(node->ln_Name);
  2419.       Remove(node);
  2420.       FreeVec(node);
  2421.     }
  2422.   }
  2423. }
  2424.  
  2425. V_BOOL __asm __saveds HBBS_SendOLM(register __d0 V_SMALLNUM FromNode,register __a0 UBYTE *FromPRG,register __d1 V_SMALLNUM ToNode,register __a1 UBYTE *MessageStr,register __d2 BYTE Pri)
  2426. {
  2427.   // frommnode should be 0 if something other than a door is sending the OLM
  2428.   // otheriwse fromnode should be set to your node number plus 1
  2429.   // e.g. N_ND->NodeNum+1, if fromnode
  2430.  
  2431.  
  2432.   V_BOOL retval=FALSE;
  2433.   struct OLMNode *NewOLM;
  2434.   struct NodeData *nd;
  2435.   struct NodeData *fnd;
  2436.   struct Message *NewMsg;
  2437.  
  2438.   // lets see if we can send an eall, node must be open and initalised with
  2439.   // a user loggined in and the status must be online
  2440.   if ((MessageStr) &&
  2441.       (FromNode>=0 ) && (FromNode<=BBSGlobal->BBSNodes) &&
  2442.       (nd=HBBS_NodeDataPtr(ToNode)) &&
  2443.       (nd->Status==STAT_ONLINE) &&
  2444.       (nd->OLMList) &&
  2445.       (nd->LoginType!=LOGIN_NONE) &&
  2446.       (nd->OnlineStatus==OS_ONLINE))
  2447.   {
  2448.     if (NewOLM=(struct OLMNode *)HBBS_CreateNode(MessageStr,sizeof(struct OLMNode)))
  2449.     {
  2450.       if (NewOLM->node.ln_Name=DupStr(MessageStr))
  2451.       {
  2452.         NewOLM->node.ln_Pri=Pri;
  2453.         HBBS_GetTime(NewOLM->Time);
  2454.         HBBS_GetDate(NewOLM->Date);
  2455.         NewOLM->FromNode=FromNode;
  2456.         if ((FromNode) && (fnd=HBBS_NodeDataPtr(FromNode-1)))
  2457.         {
  2458.           if (fnd->User.Valid) // NewOLD has already been blanked by CreateNode() so the string is already null terminated..
  2459.           {
  2460.             strNcpy(NewOLM->Handle,fnd->User.CallData.Handle,LEN_HANDLE);
  2461.           }
  2462.         }
  2463.         if (FromPRG)
  2464.         {
  2465.           strNcpy(NewOLM->FromPRG,FromPRG,LEN_HANDLE);
  2466.         }
  2467.  
  2468.         // *C* add semaphore checking!
  2469.         Enqueue(nd->OLMList,(struct Node*)NewOLM);
  2470.         nd->OLMCount++;
  2471.         if (!(nd->NodeFlags & NFLG_OLMSWAITING)) nd->NodeFlags+=NFLG_OLMSWAITING;
  2472.  
  2473.         if (nd->OLMPort)
  2474.         {
  2475.           if (NewMsg=AllocVec(sizeof (struct Message),MEMF_PUBLIC|MEMF_CLEAR))
  2476.           {
  2477.             NewMsg->mn_Node.ln_Type = NT_MESSAGE;
  2478.             NewMsg->mn_ReplyPort=NULL;
  2479.             NewMsg->mn_Length=sizeof(struct Message);
  2480.  
  2481.             PutMsg(nd->OLMPort,NewMsg);
  2482.           }
  2483.         }
  2484.         retval=TRUE;
  2485.       }
  2486.     }
  2487.   }
  2488.   return(retval);
  2489. }
  2490.  
  2491. BOOL __asm __saveds FGetsR(register __a0 BPTR FH,register __a1 UBYTE *Buffer,register __d0 LONG BufferLen)
  2492. {
  2493.  
  2494.   // fucking amazing routine to read a file line by line but BACKWARDS from the current
  2495.   // position!! Whay!!
  2496.  
  2497.   LONG nr,where,back,foundpos=0;
  2498.   BOOL retval=TRUE,sof=FALSE,error=FALSE;
  2499.  
  2500.   UBYTE *strptr=NULL;
  2501.  
  2502.  
  2503.   Buffer[0]=0;
  2504.   BufferLen--;
  2505.  
  2506.   where=Seek(FH,0,OFFSET_CURRENT);  // start of file already ?
  2507.   if (where<=0) //start of file or error
  2508.   {
  2509.     retval=FALSE;
  2510.   }
  2511.   else
  2512.   {
  2513.     do
  2514.     {
  2515.       back=255;
  2516.       if (where<255) back=where;
  2517.  
  2518.       if (back>BufferLen) back=BufferLen;
  2519.  
  2520.       if ((where=Seek(FH,0-back,OFFSET_CURRENT))!=-1)
  2521.       {
  2522.         where-=back;
  2523.  
  2524.         if (nr=Read(FH,Buffer,back))
  2525.         {
  2526.           Buffer[nr]=0;
  2527.           if (strptr=strrchr(Buffer,'\n'))
  2528.           {
  2529.             foundpos=where+(strptr-Buffer);
  2530.             if (Seek(FH,foundpos+1,OFFSET_BEGINNING)==-1)
  2531.             {
  2532.               error=TRUE;
  2533.             }
  2534.           }
  2535.           else
  2536.           {
  2537.             if (where==0)
  2538.             {
  2539.               if (Seek(FH,0,OFFSET_BEGINNING)==-1)
  2540.               {
  2541.                 error=TRUE;
  2542.               }
  2543.               else
  2544.               {
  2545.                 sof=TRUE;
  2546.                 foundpos=1;
  2547.               }
  2548.             }
  2549.             else
  2550.             {
  2551.  
  2552.               if (Seek(FH,0-nr,OFFSET_CURRENT)!=-1)
  2553.               {
  2554.                 where-=nr;
  2555.               }
  2556.               else
  2557.               {
  2558.                 error=TRUE;
  2559.               }
  2560.             }
  2561.  
  2562.           }
  2563.         }
  2564.         else
  2565.         {
  2566.           error=TRUE;
  2567.         }
  2568.  
  2569.       }
  2570.     } while (strptr==NULL && !error && !sof);
  2571.  
  2572.     Buffer[0]=0;
  2573.     if (strptr || sof )
  2574.     {
  2575.       FGets(FH,Buffer,BufferLen);
  2576.       Seek(FH,foundpos ? foundpos-1 : 0,OFFSET_BEGINNING);
  2577.     }
  2578.   }
  2579.  
  2580.   return(retval);
  2581.  
  2582. }
  2583.  
  2584. V_BOOL __asm __saveds HBBS_HandleNameOK(register __a0 char *checkstr)
  2585. {
  2586.   if (strchr(checkstr,',')) return(FALSE);
  2587.   if (strchr(checkstr,';')) return(FALSE);
  2588.   if (strchr(checkstr,'?')) return(FALSE);
  2589.   if (strchr(checkstr,'*')) return(FALSE);
  2590.   if (strchr(checkstr,'#')) return(FALSE);       // *C* optimze me..
  2591.   if (strchr(checkstr,'(')) return(FALSE);
  2592.   if (strchr(checkstr,')')) return(FALSE);
  2593.   return(TRUE);
  2594. }
  2595.  
  2596.